day 18 puzzle 1
This commit is contained in:
		
							
								
								
									
										148
									
								
								src/day18/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/day18/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| #import "/src/utils.typ": * | ||||
|  | ||||
| #let offsets = ( | ||||
|   (1, 0), | ||||
|   (0, 1), | ||||
|   (-1, 0), | ||||
|   (0, -1) | ||||
| ) | ||||
|  | ||||
| #let get-coords(x, y) = { | ||||
|   return str(x) + "/" + str(y) | ||||
| } | ||||
|  | ||||
| #let get-lowest(nodes, scores) = { | ||||
|   let lowest-score = none | ||||
|   let lowest-i = none | ||||
|   for (i, (x, y)) in nodes.enumerate() { | ||||
|     let score = scores.at(y).at(x) | ||||
|  | ||||
|     if lowest-i == none or score < lowest-score { | ||||
|       lowest-score = score | ||||
|       lowest-i = i | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if lowest-i == none { | ||||
|     panic() | ||||
|   } | ||||
|   return lowest-i | ||||
| } | ||||
|  | ||||
| #let make-path(parents, end) = { | ||||
|   let path = (end,) | ||||
|   let (x, y) = end | ||||
|   let pos = parents.at(y).at(x) | ||||
|   while pos != none { | ||||
|     (x, y) = pos | ||||
|     path.insert(0, pos) | ||||
|     pos = parents.at(y).at(x) | ||||
|   } | ||||
|   return path | ||||
| } | ||||
|  | ||||
| #let find-path(w, h, grid, start: (0, 0), end: auto) = { | ||||
|   let end = if end == auto {(w - 1, h - 1)} else {end} | ||||
|   let end = (w - 1, h - 1) | ||||
|   let (x, y) = (0, 0) | ||||
|   let open = ((x, y),) | ||||
|   let closed = () | ||||
|   let g-scores = ((0,) * w,) * h | ||||
|   let f-scores = ((calc.inf,) * w,) * h | ||||
|   let parents = ((none,)*w,)*h | ||||
|   while open.len() != 0 { | ||||
|     let cur = open.remove(get-lowest(open, f-scores)) | ||||
|      | ||||
|     if cur == end { | ||||
|       return make-path(parents, cur) | ||||
|     } | ||||
|  | ||||
|     let g-score = g-scores.at(y).at(x) | ||||
|     let f-score = f-scores.at(y).at(x) | ||||
|      | ||||
|     let (x, y) = cur | ||||
|     for (dx, dy) in offsets { | ||||
|       let (x2, y2) = (x + dx, y + dy) | ||||
|       if x2 < 0 or x2 >= w or y2 < 0 or y2 >= h { | ||||
|         continue | ||||
|       } | ||||
|       if grid.at(y2).at(x2) { | ||||
|         continue | ||||
|       } | ||||
|       if (x2, y2) in closed { | ||||
|         continue | ||||
|       } | ||||
|       let g = x2 + y2 | ||||
|       let h = calc.abs(end.first() - x2) + calc.abs(end.last() - y2) | ||||
|       let f = g + h | ||||
|  | ||||
|       if f < f-scores.at(y2).at(x2) { | ||||
|         g-scores.at(y2).at(x2) = g | ||||
|         f-scores.at(y2).at(x2) = f | ||||
|         parents.at(y2).at(x2) = (x, y) | ||||
|         open.push((x2, y2)) | ||||
|       } | ||||
|     } | ||||
|     closed.push(cur) | ||||
|   } | ||||
|   panic("No path was found") | ||||
| } | ||||
|  | ||||
| #let solve(input, w: 0, h: 0, n-bytes: 0) = { | ||||
|   assert(w != 0, message: "Width cannot be 0") | ||||
|   assert(h != 0, message: "Height cannot be 0") | ||||
|   let grid = ((false,) * w,) * h | ||||
|  | ||||
|   let obstacles = input.split("\n") | ||||
|   for obs in obstacles.slice(0, n-bytes) { | ||||
|     let (x, y) = obs.split(",").map(int) | ||||
|     grid.at(y).at(x) = true | ||||
|   } | ||||
|  | ||||
|   let path = find-path(w, h, grid) | ||||
|   return path.len() - 1 | ||||
| } | ||||
|  | ||||
| #let visualize(input, w: 0, h: 0, n-bytes: 0, s: 2em) = { | ||||
|   let grid_ = ((false,) * w,) * h | ||||
|  | ||||
|   let obstacles = input.split("\n") | ||||
|   for obs in obstacles.slice(0, n-bytes) { | ||||
|     let (x, y) = obs.split(",").map(int) | ||||
|     grid_.at(y).at(x) = true | ||||
|   } | ||||
|  | ||||
|   let path = find-path(w, h, grid_) | ||||
|   for (x, y) in path { | ||||
|     grid_.at(y).at(x) = grid.cell(fill: green.lighten(60%))[O] | ||||
|   } | ||||
|    | ||||
|   let cells = grid_.flatten().map(c => { | ||||
|     if c == false [] | ||||
|     else if c == true {grid.cell(fill: red.lighten(60%))[\#]} | ||||
|     else {c} | ||||
|   }) | ||||
|    | ||||
|   grid( | ||||
|     columns: (s,) * w, | ||||
|     rows: (s,) * h, | ||||
|     align: center + horizon, | ||||
|     stroke: black, | ||||
|     ..cells | ||||
|   ) | ||||
| } | ||||
|  | ||||
| #show-puzzle( | ||||
|   18, 1, | ||||
|   solve.with(w: 71, h: 71, n-bytes: 1024), | ||||
|   example: ( | ||||
|     (result: 22, args: (w: 7, h: 7, n-bytes: 12)), | ||||
|   ), | ||||
|   visualize: visualize.with(w: 7, h: 7, n-bytes: 12) | ||||
| ) | ||||
|  | ||||
| /* | ||||
| #pagebreak() | ||||
| #set page(width: auto, height: auto) | ||||
| #visualize(get-input(18), w: 71, h: 71, n-bytes: 1024, s: 1em) | ||||
| */ | ||||
							
								
								
									
										0
									
								
								src/day18/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/day18/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/main.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main.pdf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user