solve_2_attempt_toolong.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "math"
  6. "os"
  7. //"slices"
  8. "strconv"
  9. "strings"
  10. )
  11. var red_walls [][]int
  12. var lines map[int][][]int
  13. var columns map[int][][]int
  14. var the_map map[[2]int]byte
  15. var max_x,min_x int
  16. var max_y,min_y int
  17. func main() {
  18. fmt.Println("Advent of Code 2025 - Day 9 - Part 2")
  19. f,_:= os.Open("9/input")
  20. defer f.Close()
  21. scanner:=bufio.NewScanner(f)
  22. max_x = 0
  23. min_x = math.MaxInt
  24. max_y = 0
  25. min_y = math.MaxInt
  26. the_map = make(map[[2]int]byte)
  27. for scanner.Scan(){
  28. line:= scanner.Text()
  29. line_sp := strings.Split(line, ",")
  30. x,_:= strconv.Atoi(line_sp[0])
  31. y,_:= strconv.Atoi(line_sp[1])
  32. max_x = max(x,max_x)
  33. min_x = min(x,min_x)
  34. max_y = max(y,max_y)
  35. min_y = min(y,min_y)
  36. red_walls = append(red_walls, []int{x,y})
  37. the_map[[2]int{x,y}] = '#'
  38. }
  39. construct_border()
  40. //fmt.Println(len(lines))
  41. //fmt.Println(len(columns))
  42. construct_map()
  43. print_map()
  44. res := int64(0)
  45. for i:= range red_walls {
  46. w1:= red_walls[i]
  47. for j:= i+1; j < len(red_walls); j++{
  48. w2:= red_walls[j]
  49. if (is_valid_area(w1,w2)){
  50. area := calculate_area2(w1,w2)
  51. if area > res {
  52. // fmt.Println(w1,w2)
  53. res = area
  54. }
  55. }
  56. }
  57. }
  58. fmt.Println(res)
  59. }
  60. func construct_map(){
  61. for i:= min_x; i <= max_x; i++ {
  62. for j:= min_y; j <= max_y; j++{
  63. if the_map[[2]int{i,j}] != '#'{
  64. if is_green_or_red([]int{i,j}) {
  65. the_map[[2]int{i,j}] = 'O'
  66. } else {
  67. the_map[[2]int{i,j}] = '.'
  68. }
  69. }
  70. }
  71. }
  72. }
  73. func print_map(){
  74. for i := range 15 {
  75. for j:= range 15{
  76. c,ok := the_map[[2]int{j,i}]
  77. if ok {
  78. fmt.Printf(string(c))
  79. } else {
  80. fmt.Printf(".")
  81. }
  82. }
  83. fmt.Printf("\n")
  84. }
  85. }
  86. func construct_border() {
  87. lines = make(map[int][][]int)
  88. columns = make(map[int][][]int)
  89. for i:= 0; i < len(red_walls); i++{
  90. px,py := red_walls[(i+1)%len(red_walls)][0], red_walls[(i+1)%len(red_walls)][1]
  91. x,y:= red_walls[i][0], red_walls[i][1]
  92. if x == px {
  93. // lines from min(y,py) to max(y,py)
  94. for ln := min(y, py); ln <= max(y, py); ln++ {
  95. new_l := true
  96. _,ok := lines[ln]
  97. if ok{
  98. for i:= range lines[ln] {
  99. if lines[ln][i][0] <= x && x <= lines[ln][i][1] {
  100. lines[ln][i][0] = min(lines[ln][i][0], x)
  101. lines[ln][i][1] = max(lines[ln][i][1], x)
  102. new_l = false
  103. break
  104. }
  105. }
  106. }
  107. if new_l{
  108. lines[ln] = append(lines[ln], []int{x,x})
  109. }
  110. }
  111. // column x
  112. new_c := true
  113. a,b := min(y,py), max(y,py)
  114. _,ok := columns[x]
  115. if ok{
  116. for i:= range columns[x] {
  117. if columns[x][i][0] <= a && a <= columns[x][i][1] {
  118. columns[x][i][0] = min(columns[x][i][0], a)
  119. columns[x][i][1] = max(columns[x][i][1], b)
  120. new_c = false
  121. break
  122. }
  123. }
  124. }
  125. if new_c{
  126. columns[x] = append(columns[x], []int{a,b})
  127. }
  128. } else if y == py {
  129. // line y
  130. new_l := true
  131. a,b := min(x,px), max(x,px)
  132. _,ok := lines[y]
  133. if ok{
  134. for i:= range lines[y] {
  135. if lines[y][i][0] <= a && a <= lines[y][i][1] {
  136. lines[y][i][0] = min(lines[y][i][0], a)
  137. lines[y][i][1] = max(lines[y][i][1], b)
  138. new_l = false
  139. break
  140. }
  141. }
  142. }
  143. if new_l{
  144. lines[y] = append(lines[y], []int{min(x,px),max(x,px)})
  145. }
  146. // columns from min(x,px) to max(x,px)
  147. for cn := min(x, px); cn <= max(x, px); cn++ {
  148. new_c := true
  149. _,ok := columns[cn]
  150. if ok{
  151. for i:= range columns[cn] {
  152. if columns[cn][i][0] <= y && y <= columns[cn][i][1] {
  153. columns[cn][i][0] = min(columns[cn][i][0], y)
  154. columns[cn][i][1] = max(columns[cn][i][1], y)
  155. new_c = false
  156. break
  157. }
  158. }
  159. }
  160. if new_c{
  161. columns[cn] = append(columns[cn], []int{y,y})
  162. }
  163. }
  164. }
  165. }
  166. }
  167. // Given a point []int{x,y} look for the border to the 4 directions (W,N,E,S)
  168. // B_W should have same y and <= x
  169. // B_E should have same y and >= x
  170. // B_N should have same x and >= y
  171. // B_S should have same x and <= y
  172. // if all borders are found then the point is a green or red wall
  173. // otherwise it's out of boundaries
  174. func is_green_or_red(w []int) bool {
  175. if is_border(w) {
  176. return true
  177. }
  178. ok_bw,ok_be := false,false
  179. ok_bn,ok_bs := false,false
  180. x,y := w[0],w[1]
  181. _,ok:= lines[y]
  182. if !ok {
  183. return false
  184. }
  185. _,ok = columns[x]
  186. if !ok {
  187. return false
  188. }
  189. // look for bordeer B_w & B_E
  190. for i:= range lines[y] {
  191. if ok_bw && ok_be{
  192. break
  193. }
  194. if !ok_bw && (lines[y][i][0] <= x || lines[y][i][1] <= x) {
  195. ok_bw = true
  196. }
  197. if !ok_be && (lines[y][i][0] >= x || lines[y][i][1] >= x) {
  198. ok_be = true
  199. }
  200. }
  201. if !ok_bw || !ok_be{
  202. return false
  203. }
  204. // look for bordeer B_N & B_S
  205. for i:= range columns[x] {
  206. if ok_bn && ok_bs{
  207. break
  208. }
  209. if !ok_bn && (columns[x][i][0] >= y || columns[x][i][1] >= y) {
  210. ok_bn = true
  211. }
  212. if !ok_bs && (columns[x][i][0] <= y || columns[x][i][1] <= y) {
  213. ok_bs = true
  214. }
  215. }
  216. if !ok_bw || !ok_be{
  217. return false
  218. }
  219. return ok_be && ok_bw && ok_bn && ok_bs
  220. }
  221. func is_valid_area(w1,w2 []int) bool{
  222. x1,y1:=w1[0],w1[1]
  223. x2,y2:=w2[0],w2[1]
  224. start_x, end_x := min(x1,x2), max(x1,x2) // 2,11
  225. start_y, end_y := min(y1,y2), max(y1,y2) // 1,5
  226. for i:= start_x+1; i < end_x; i++{
  227. if (the_map[[2]int{i,y1}] == '.'){
  228. return false
  229. }
  230. if (the_map[[2]int{i,y2}] == '.'){
  231. return false
  232. }
  233. }
  234. for i:= start_y+1; i < end_y; i++{
  235. if (the_map[[2]int{x2,i}]== '.'){
  236. return false
  237. }
  238. if (the_map[[2]int{x1,i}] == '.'){
  239. return false
  240. }
  241. }
  242. return true
  243. }
  244. func is_border(w []int) bool {
  245. borders, ok := lines[w[1]]
  246. if ok {
  247. for i:= range borders{
  248. if borders[i][0] <= w[0] && w[0] <= borders[i][1]{
  249. return true
  250. }
  251. }
  252. }
  253. return false
  254. }
  255. func calculate_area2(w1,w2 []int) int64{
  256. dx, dy := int64(math.Abs(float64(w1[0]-w2[0]))), int64(math.Abs(float64(w1[1]-w2[1])))
  257. return (dx+1) * (dy+1)
  258. }