solve_2_attempt2.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "math"
  6. "os"
  7. "sort"
  8. //"slices"
  9. "strconv"
  10. "strings"
  11. )
  12. var red_walls [][2]int
  13. var the_map map[[2]int]byte
  14. var max_x,min_x int
  15. var max_y,min_y int
  16. func main() {
  17. fmt.Println("Advent of Code 2025 - Day 9 - Part 2")
  18. f,_:= os.Open("9/test")
  19. defer f.Close()
  20. scanner:=bufio.NewScanner(f)
  21. max_x = 0
  22. min_x = math.MaxInt
  23. max_y = 0
  24. min_y = math.MaxInt
  25. the_map = make(map[[2]int]byte)
  26. for scanner.Scan(){
  27. line:= scanner.Text()
  28. line_sp := strings.Split(line, ",")
  29. x,_:= strconv.Atoi(line_sp[0])
  30. y,_:= strconv.Atoi(line_sp[1])
  31. max_x = max(x,max_x)
  32. min_x = min(x,min_x)
  33. max_y = max(y,max_y)
  34. min_y = min(y,min_y)
  35. red_walls = append(red_walls, [2]int{x,y})
  36. the_map[[2]int{x,y}] = '#'
  37. }
  38. construct_border()
  39. store_borders()
  40. print_map()
  41. res := int64(0)
  42. for i:= range red_walls {
  43. w1:= red_walls[i]
  44. for j:= i+1; j < len(red_walls); j++{
  45. w2:= red_walls[j]
  46. if (is_valid_area(w1,w2)){
  47. area := calculate_area2(w1,w2)
  48. if area > res {
  49. // fmt.Println(w1,w2)
  50. res = area
  51. }
  52. }
  53. }
  54. }
  55. fmt.Println(row_borders)
  56. fmt.Println(col_borders)
  57. fmt.Println(res)
  58. }
  59. var row_borders = map[int][]int{}
  60. var col_borders = map[int][]int{}
  61. func store_borders(){
  62. for p := range the_map {
  63. x,y := p[0], p[1]
  64. row_borders[y] = append(row_borders[y],x)
  65. col_borders[x] = append(col_borders[x],y)
  66. }
  67. for y:= range row_borders{
  68. sort.Ints(row_borders[y])
  69. }
  70. for x:= range col_borders{
  71. sort.Ints(col_borders[x])
  72. }
  73. }
  74. func print_map(){
  75. for i := range 15 {
  76. for j:= range 15{
  77. c,ok := the_map[[2]int{j,i}]
  78. if ok {
  79. fmt.Printf(string(c))
  80. } else {
  81. fmt.Printf(".")
  82. }
  83. }
  84. fmt.Printf("\n")
  85. }
  86. }
  87. func construct_border() {
  88. for i:= 0; i < len(red_walls); i++{
  89. px,py := red_walls[(i+1)%len(red_walls)][0], red_walls[(i+1)%len(red_walls)][1]
  90. x,y:= red_walls[i][0], red_walls[i][1]
  91. if x == px {
  92. //points from min(y,py) to max(y,py)
  93. for ln := min(y,py)+1; ln < max(y,py); ln++{
  94. the_map[[2]int{x,ln}] = 'O'
  95. }
  96. }
  97. if y == py {
  98. //points from min(x,px) to max(x,px)
  99. for ln := min(x,px)+1; ln < max(x,px); ln++{
  100. the_map[[2]int{ln,y}] = 'O'
  101. }
  102. }
  103. }
  104. }
  105. // Given a point []int{x,y} look for the border to the 4 directions (W,N,E,S)
  106. // B_W should have same y and <= x
  107. // B_E should have same y and >= x
  108. // B_N should have same x and >= y
  109. // B_S should have same x and <= y
  110. // if all borders are found then the point is a green or red wall
  111. // otherwise it's out of boundaries
  112. var green_cache = map[[2]int]bool{}
  113. func is_green(w [2]int) bool {
  114. if v, ok := green_cache[w]; ok {
  115. return v
  116. }
  117. ok_bw,ok_be := false,false
  118. ok_bn,ok_bs := false,false
  119. glob_ok := true
  120. x,y := w[0],w[1]
  121. _,ok:= the_map[w]
  122. if ok {
  123. green_cache[w] = true
  124. return true
  125. }
  126. xs, ok := row_borders[y]
  127. if !ok{
  128. green_cache[w] = false
  129. return false
  130. }
  131. ys, ok:= col_borders[x]
  132. if !ok{
  133. green_cache[w] = false
  134. return false
  135. }
  136. i := sort.SearchInts(xs,x)
  137. ok_be = (i!=0)
  138. ok_bw = (i!=len(xs))
  139. glob_ok = glob_ok && ok_be && ok_bw
  140. if !glob_ok {
  141. green_cache[w] = false
  142. return false
  143. }
  144. j:= sort.SearchInts(ys,y)
  145. ok_bn = (j!=0)
  146. ok_bs = (j!=len(ys))
  147. glob_ok = glob_ok && ok_bn && ok_bs
  148. green_cache[w] = glob_ok
  149. return glob_ok
  150. }
  151. func is_valid_area(w1,w2 [2]int) bool{
  152. x1,y1:=w1[0],w1[1]
  153. x2,y2:=w2[0],w2[1]
  154. w3 := [2]int{x1,y2}
  155. w4 := [2]int{x2,y1}
  156. return is_valid_line(w1,w4) && is_valid_line(w2,w4) && is_valid_line(w2,w3) && is_valid_line(w3,w1)
  157. }
  158. var valid_line_cache = map[[2][2]int]bool{}
  159. func is_valid_line(w1,w2 [2]int) bool{
  160. if v, ok := valid_line_cache[[2][2]int{w1,w2}]; ok {
  161. return v
  162. }
  163. x1,y1:=w1[0],w1[1]
  164. x2,y2:=w2[0],w2[1]
  165. if x1 == x1 && y1 == y2 {
  166. valid_line_cache[[2][2]int{w1,w2}] = true
  167. return true
  168. }
  169. if x1 == x2 {
  170. start_y := min(y1,y2)
  171. end_y := max(y1,y2)
  172. for i:= start_y; i <= end_y; i++{
  173. if (!is_green([2]int{x1,i})){
  174. valid_line_cache[[2][2]int{w1,w2}] = false
  175. return false
  176. }
  177. }
  178. } else if y1 == y2 {
  179. start_x := min(x1,x2)
  180. end_x := max(x1,x2)
  181. for i:= start_x; i <= end_x; i++{
  182. if (!is_green([2]int{i,y1})){
  183. valid_line_cache[[2][2]int{w1,w2}] = false
  184. return false
  185. }
  186. }
  187. } else {
  188. valid_line_cache[[2][2]int{w1,w2}] = false
  189. return false
  190. }
  191. valid_line_cache[[2][2]int{w1,w2}] = true
  192. return true
  193. }
  194. func calculate_area2(w1,w2 [2]int) int64{
  195. dx, dy := int64(math.Abs(float64(w1[0]-w2[0]))), int64(math.Abs(float64(w1[1]-w2[1])))
  196. return (dx+1) * (dy+1)
  197. }