Compare commits
	
		
			11 Commits
		
	
	
		
			953716b95a
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 93e365d10b | |||
| 9300d786f8 | |||
| ec75800078 | |||
| 16a0d9b3f8 | |||
| d830919adc | |||
| 056e29b96c | |||
| 47fbeb1ce9 | |||
| 4826c0d21e | |||
| 0950e76d8d | |||
| 5921a90c73 | |||
| 4a429bd62b | 
							
								
								
									
										26
									
								
								day22.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								day22.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | with open("res/inputs/day22.txt", "r") as f: | ||||||
|  |     values = list(map(int, f.read().split("\n"))) | ||||||
|  |  | ||||||
|  | calls = 0 | ||||||
|  |  | ||||||
|  | def step(a, shift): | ||||||
|  |     global calls | ||||||
|  |     calls += 1 | ||||||
|  |     s = (a >> -shift) if shift < 0 else (a << shift) | ||||||
|  |     return (s ^ a) & 0xffffff | ||||||
|  |  | ||||||
|  | def rand(value): | ||||||
|  |     b = step(value, 6) | ||||||
|  |     c = step(b, -5) | ||||||
|  |     d = step(c, 11) | ||||||
|  |     return d | ||||||
|  |  | ||||||
|  |  | ||||||
|  | total = 0 | ||||||
|  | for v in values: | ||||||
|  |     for _ in range(2000): | ||||||
|  |         v = rand(v) | ||||||
|  |     total += v | ||||||
|  |  | ||||||
|  | print(total) | ||||||
|  | print(calls) | ||||||
							
								
								
									
										
											BIN
										
									
								
								progress.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								progress.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 135 KiB | 
| @@ -34,3 +34,17 @@ | |||||||
|   stars: 1 |   stars: 1 | ||||||
| 18: | 18: | ||||||
|   stars: 2 |   stars: 2 | ||||||
|  | 19: | ||||||
|  |   stars: 2 | ||||||
|  | 20: | ||||||
|  |   stars: 1 | ||||||
|  | 21: | ||||||
|  |   stars: 0 | ||||||
|  | 22: | ||||||
|  |   stars: 1 | ||||||
|  | 23: | ||||||
|  |   stars: 2 | ||||||
|  | 24: | ||||||
|  |   stars: 1 | ||||||
|  | 25: | ||||||
|  |   stars: 1 | ||||||
							
								
								
									
										10
									
								
								res/examples/day19.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								res/examples/day19.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | r, wr, b, g, bwu, rb, gb, br | ||||||
|  |  | ||||||
|  | brwrr | ||||||
|  | bggr | ||||||
|  | gbbr | ||||||
|  | rrbgbr | ||||||
|  | ubwu | ||||||
|  | bwurrg | ||||||
|  | brgr | ||||||
|  | bbrgwb | ||||||
							
								
								
									
										15
									
								
								res/examples/day20.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								res/examples/day20.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | ############### | ||||||
|  | #...#...#.....# | ||||||
|  | #.#.#.#.#.###.# | ||||||
|  | #S#...#.#.#...# | ||||||
|  | #######.#.#.### | ||||||
|  | #######.#.#...# | ||||||
|  | #######.#.###.# | ||||||
|  | ###..E#...#...# | ||||||
|  | ###.#######.### | ||||||
|  | #...###...#...# | ||||||
|  | #.#####.#.###.# | ||||||
|  | #.#...#.#.#...# | ||||||
|  | #.#.#.#.#.#.### | ||||||
|  | #...#...#...### | ||||||
|  | ############### | ||||||
							
								
								
									
										5
									
								
								res/examples/day21.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								res/examples/day21.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | 029A | ||||||
|  | 980A | ||||||
|  | 179A | ||||||
|  | 456A | ||||||
|  | 379A | ||||||
							
								
								
									
										1
									
								
								res/examples/day22.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								res/examples/day22.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | 123 | ||||||
							
								
								
									
										32
									
								
								res/examples/day23.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								res/examples/day23.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | kh-tc | ||||||
|  | qp-kh | ||||||
|  | de-cg | ||||||
|  | ka-co | ||||||
|  | yn-aq | ||||||
|  | qp-ub | ||||||
|  | cg-tb | ||||||
|  | vc-aq | ||||||
|  | tb-ka | ||||||
|  | wh-tc | ||||||
|  | yn-cg | ||||||
|  | kh-ub | ||||||
|  | ta-co | ||||||
|  | de-co | ||||||
|  | tc-td | ||||||
|  | tb-wq | ||||||
|  | wh-td | ||||||
|  | ta-ka | ||||||
|  | td-qp | ||||||
|  | aq-cg | ||||||
|  | wq-ub | ||||||
|  | ub-vc | ||||||
|  | de-ta | ||||||
|  | wq-aq | ||||||
|  | wq-vc | ||||||
|  | wh-yn | ||||||
|  | ka-de | ||||||
|  | kh-ta | ||||||
|  | co-tc | ||||||
|  | wh-qp | ||||||
|  | tb-vc | ||||||
|  | td-yn | ||||||
							
								
								
									
										10
									
								
								res/examples/day24_1.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								res/examples/day24_1.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | x00: 1 | ||||||
|  | x01: 1 | ||||||
|  | x02: 1 | ||||||
|  | y00: 0 | ||||||
|  | y01: 1 | ||||||
|  | y02: 0 | ||||||
|  |  | ||||||
|  | x00 AND y00 -> z00 | ||||||
|  | x01 XOR y01 -> z01 | ||||||
|  | x02 OR y02 -> z02 | ||||||
							
								
								
									
										47
									
								
								res/examples/day24_2.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								res/examples/day24_2.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | x00: 1 | ||||||
|  | x01: 0 | ||||||
|  | x02: 1 | ||||||
|  | x03: 1 | ||||||
|  | x04: 0 | ||||||
|  | y00: 1 | ||||||
|  | y01: 1 | ||||||
|  | y02: 1 | ||||||
|  | y03: 1 | ||||||
|  | y04: 1 | ||||||
|  |  | ||||||
|  | ntg XOR fgs -> mjb | ||||||
|  | y02 OR x01 -> tnw | ||||||
|  | kwq OR kpj -> z05 | ||||||
|  | x00 OR x03 -> fst | ||||||
|  | tgd XOR rvg -> z01 | ||||||
|  | vdt OR tnw -> bfw | ||||||
|  | bfw AND frj -> z10 | ||||||
|  | ffh OR nrd -> bqk | ||||||
|  | y00 AND y03 -> djm | ||||||
|  | y03 OR y00 -> psh | ||||||
|  | bqk OR frj -> z08 | ||||||
|  | tnw OR fst -> frj | ||||||
|  | gnj AND tgd -> z11 | ||||||
|  | bfw XOR mjb -> z00 | ||||||
|  | x03 OR x00 -> vdt | ||||||
|  | gnj AND wpb -> z02 | ||||||
|  | x04 AND y00 -> kjc | ||||||
|  | djm OR pbm -> qhw | ||||||
|  | nrd AND vdt -> hwm | ||||||
|  | kjc AND fst -> rvg | ||||||
|  | y04 OR y02 -> fgs | ||||||
|  | y01 AND x02 -> pbm | ||||||
|  | ntg OR kjc -> kwq | ||||||
|  | psh XOR fgs -> tgd | ||||||
|  | qhw XOR tgd -> z09 | ||||||
|  | pbm OR djm -> kpj | ||||||
|  | x03 XOR y03 -> ffh | ||||||
|  | x00 XOR y04 -> ntg | ||||||
|  | bfw OR bqk -> z06 | ||||||
|  | nrd XOR fgs -> wpb | ||||||
|  | frj XOR qhw -> z04 | ||||||
|  | bqk OR frj -> z07 | ||||||
|  | y03 OR x01 -> nrd | ||||||
|  | hwm AND bqk -> z03 | ||||||
|  | tgd XOR rvg -> z12 | ||||||
|  | tnw OR pbm -> gnj | ||||||
							
								
								
									
										39
									
								
								res/examples/day25.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								res/examples/day25.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | ##### | ||||||
|  | .#### | ||||||
|  | .#### | ||||||
|  | .#### | ||||||
|  | .#.#. | ||||||
|  | .#... | ||||||
|  | ..... | ||||||
|  |  | ||||||
|  | ##### | ||||||
|  | ##.## | ||||||
|  | .#.## | ||||||
|  | ...## | ||||||
|  | ...#. | ||||||
|  | ...#. | ||||||
|  | ..... | ||||||
|  |  | ||||||
|  | ..... | ||||||
|  | #.... | ||||||
|  | #.... | ||||||
|  | #...# | ||||||
|  | #.#.# | ||||||
|  | #.### | ||||||
|  | ##### | ||||||
|  |  | ||||||
|  | ..... | ||||||
|  | ..... | ||||||
|  | #.#.. | ||||||
|  | ###.. | ||||||
|  | ###.# | ||||||
|  | ###.# | ||||||
|  | ##### | ||||||
|  |  | ||||||
|  | ..... | ||||||
|  | ..... | ||||||
|  | ..... | ||||||
|  | #.... | ||||||
|  | #.#.. | ||||||
|  | #.#.# | ||||||
|  | ##### | ||||||
							
								
								
									
										41
									
								
								src/day19/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/day19/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let is-possible(target, towels: none) = { | ||||||
|  |   if towels == none { | ||||||
|  |     panic() | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   for towel in towels { | ||||||
|  |     if towel == target { | ||||||
|  |       return true | ||||||
|  |     } | ||||||
|  |     if target.starts-with(towel) { | ||||||
|  |       if is-possible(target.slice(towel.len()), towels: towels) { | ||||||
|  |         return true | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let (towels, targets) = input.split("\n\n") | ||||||
|  |  | ||||||
|  |   towels = towels.split(", ") | ||||||
|  |   let is-possible = is-possible.with(towels: towels) | ||||||
|  |  | ||||||
|  |   let total = 0 | ||||||
|  |   for target in targets.split("\n") { | ||||||
|  |     if is-possible(target) { | ||||||
|  |       total += 1 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   19, 1, | ||||||
|  |   solve, | ||||||
|  |   example: 6 | ||||||
|  | ) | ||||||
							
								
								
									
										46
									
								
								src/day19/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/day19/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let (towels, targets) = input.split("\n\n") | ||||||
|  |  | ||||||
|  |   towels = towels.split(", ") | ||||||
|  |   let by-initial = (:) | ||||||
|  |   for towel in towels { | ||||||
|  |     let initial = towel.first() | ||||||
|  |     if initial not in by-initial { | ||||||
|  |       by-initial.insert(initial, ()) | ||||||
|  |     } | ||||||
|  |     by-initial.at(initial).push(towel) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let count(target) = { | ||||||
|  |     let initial = target.first() | ||||||
|  |     if initial not in by-initial { | ||||||
|  |       return 0 | ||||||
|  |     } | ||||||
|  |     let cnt = 0 | ||||||
|  |     for towel in by-initial.at(initial) { | ||||||
|  |       if towel == target { | ||||||
|  |         cnt += 1 | ||||||
|  |       } else if target.starts-with(towel) { | ||||||
|  |         cnt += count(target.slice(towel.len())) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return cnt | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let total = 0 | ||||||
|  |   for target in targets.split("\n") { | ||||||
|  |     total += count(target) | ||||||
|  |   } | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   19, 2, | ||||||
|  |   solve, | ||||||
|  |   example: 16, | ||||||
|  |   only-example: true | ||||||
|  | ) | ||||||
|  | #show-result(632423618484345) | ||||||
							
								
								
									
										128
									
								
								src/day20/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/day20/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let offsets = ( | ||||||
|  |   (1, 0), | ||||||
|  |   (0, 1), | ||||||
|  |   (-1, 0), | ||||||
|  |   (0, -1) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | #let EMPTY = "." | ||||||
|  | #let WALL = "#" | ||||||
|  | #let START = "S" | ||||||
|  | #let END = "E" | ||||||
|  |  | ||||||
|  | #let in-grid(w, h, x, y) = { | ||||||
|  |   return 0 <= x and x < w and 0 <= y and y < h | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let count-shortcuts(grid, w, h, save, path) = { | ||||||
|  |   let in-grid = in-grid.with(w, h) | ||||||
|  |   let total = 0 | ||||||
|  |   for (x1, y1) in path { | ||||||
|  |     let v1 = grid.at(y1).at(x1) | ||||||
|  |  | ||||||
|  |     for (dx1, dy1) in offsets { | ||||||
|  |       let (x2, y2) = (x1 + dx1, y1 + dy1) | ||||||
|  |       if not in-grid(x2, y2) { | ||||||
|  |         continue | ||||||
|  |       } | ||||||
|  |       let v2 = grid.at(y2).at(x2) | ||||||
|  |       if v2 < 0 { | ||||||
|  |         for (dx2, dy2) in offsets { | ||||||
|  |           let (x3, y3) = (x2 + dx2, y2 + dy2) | ||||||
|  |           if not in-grid(x3, y3) { | ||||||
|  |             continue | ||||||
|  |           } | ||||||
|  |           let v3 = grid.at(y3).at(x3) | ||||||
|  |           if v3 > 0 { | ||||||
|  |             if v3 - v1 >= save + 2 { | ||||||
|  |               total += 1 | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let solve(input, save: 1) = { | ||||||
|  |   let input-grid = input.split("\n").map(l => l.clusters()) | ||||||
|  |  | ||||||
|  |   let w = input-grid.first().len() | ||||||
|  |   let h = input-grid.len() | ||||||
|  |   let in-grid = in-grid.with(w, h) | ||||||
|  |  | ||||||
|  |   let grid = ((-1,)*w,)*h | ||||||
|  |   let start = none | ||||||
|  |   let end = none | ||||||
|  |   for y in range(h) { | ||||||
|  |     for x in range(w) { | ||||||
|  |       let c = input-grid.at(y).at(x) | ||||||
|  |       if c == WALL { | ||||||
|  |         continue | ||||||
|  |       } | ||||||
|  |       if c == START { | ||||||
|  |         start = (x, y) | ||||||
|  |       } else if c == END { | ||||||
|  |         end = (x, y) | ||||||
|  |       } | ||||||
|  |       grid.at(y).at(x) = 0 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let (x, y) = start | ||||||
|  |   let (ex, ey) = end | ||||||
|  |   let path = () | ||||||
|  |  | ||||||
|  |   while x != ex or y != ey { | ||||||
|  |     path.push((x, y)) | ||||||
|  |     grid.at(y).at(x) = path.len() | ||||||
|  |     for (dx, dy) in offsets { | ||||||
|  |       let (x2, y2) = (x + dx, y + dy) | ||||||
|  |       if not in-grid(x2, y2) { | ||||||
|  |         continue | ||||||
|  |       } | ||||||
|  |       let v = grid.at(y2).at(x2) | ||||||
|  |       if v == 0 { | ||||||
|  |         (x, y) = (x2, y2) | ||||||
|  |         break | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   path.push((x, y)) | ||||||
|  |   grid.at(y).at(x) = path.len() | ||||||
|  |  | ||||||
|  |   return count-shortcuts( | ||||||
|  |     grid, w, h, | ||||||
|  |     save, | ||||||
|  |     path | ||||||
|  |   ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let examples = ( | ||||||
|  |   (64, 1), | ||||||
|  |   (40, 1), | ||||||
|  |   (38, 1), | ||||||
|  |   (36, 1), | ||||||
|  |   (20, 1), | ||||||
|  |   (12, 3), | ||||||
|  |   (10, 2), | ||||||
|  |   (8, 4), | ||||||
|  |   (6, 2), | ||||||
|  |   (4, 14), | ||||||
|  |   (2, 14), | ||||||
|  | ) | ||||||
|  | #let n-tot = 0 | ||||||
|  | #let examples2 = () | ||||||
|  | #for (save, cnt) in examples { | ||||||
|  |   n-tot += cnt | ||||||
|  |   examples2.push((result: n-tot, args: (save: save))) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   20, 1, | ||||||
|  |   solve.with(save: 100), | ||||||
|  |   example: examples2 | ||||||
|  | ) | ||||||
							
								
								
									
										0
									
								
								src/day20/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/day20/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										100
									
								
								src/day21/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/day21/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let nums = ( | ||||||
|  |   "7": (0, 0), | ||||||
|  |   "8": (1, 0), | ||||||
|  |   "9": (2, 0), | ||||||
|  |   "4": (0, 1), | ||||||
|  |   "5": (1, 1), | ||||||
|  |   "6": (2, 1), | ||||||
|  |   "1": (0, 2), | ||||||
|  |   "2": (1, 2), | ||||||
|  |   "3": (2, 2), | ||||||
|  |   "0": (1, 3), | ||||||
|  |   "A": (2, 3), | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | #let arrows = ( | ||||||
|  |   "^": (1, 0), | ||||||
|  |   "A": (2, 0), | ||||||
|  |   "<": (0, 1), | ||||||
|  |   "v": (1, 1), | ||||||
|  |   ">": (2, 1), | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | #let get-num-path(code) = { | ||||||
|  |   let path = "" | ||||||
|  |   let (x, y) = nums.at("A") | ||||||
|  |   for char in code { | ||||||
|  |     let (x2, y2) = nums.at(char) | ||||||
|  |     let dy = y2 - y | ||||||
|  |     let dx = x2 - x | ||||||
|  |     let ver = if dy == 0 { | ||||||
|  |       "" | ||||||
|  |     } else { | ||||||
|  |       (if dy < 0 {"^"} else {"v"}) * calc.abs(dy) | ||||||
|  |     } | ||||||
|  |     let hor = if dx == 0 { | ||||||
|  |       "" | ||||||
|  |     } else { | ||||||
|  |       (if dx < 0 {"<"} else {">"}) * calc.abs(dx) | ||||||
|  |     } | ||||||
|  |     path += if y == 3 and x2 == 0 { | ||||||
|  |       ver + hor | ||||||
|  |     } else { | ||||||
|  |       hor + ver | ||||||
|  |     } + "A" | ||||||
|  |     (x, y) = (x2, y2) | ||||||
|  |   } | ||||||
|  |   return path | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let get-dir-path(code) = { | ||||||
|  |   let path = "" | ||||||
|  |   let (x, y) = arrows.at("A") | ||||||
|  |   for char in code { | ||||||
|  |     let (x2, y2) = arrows.at(char) | ||||||
|  |     let dy = y2 - y | ||||||
|  |     let dx = x2 - x | ||||||
|  |     let ver = if dy == 0 { | ||||||
|  |       "" | ||||||
|  |     } else { | ||||||
|  |       (if dy < 0 {"^"} else {"v"}) * calc.abs(dy) | ||||||
|  |     } | ||||||
|  |     let hor = if dx == 0 { | ||||||
|  |       "" | ||||||
|  |     } else { | ||||||
|  |       (if dx < 0 {"<"} else {">"}) * calc.abs(dx) | ||||||
|  |     } | ||||||
|  |     path += if x == 0 and dy < 0 { | ||||||
|  |       hor + ver | ||||||
|  |     } else { | ||||||
|  |       ver + hor | ||||||
|  |     } + "A" | ||||||
|  |     (x, y) = (x2, y2) | ||||||
|  |   } | ||||||
|  |   return path | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let get-path(code) = { | ||||||
|  |   let num-path = get-num-path(code) | ||||||
|  |   let dir-path-1 = get-dir-path(num-path) | ||||||
|  |   let dir-path-2 = get-dir-path(dir-path-1) | ||||||
|  |   return dir-path-2 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let codes = input.split("\n") | ||||||
|  |   let total = 0 | ||||||
|  |   for code in codes { | ||||||
|  |     let len = get-path(code).len() | ||||||
|  |     let num = int(code.slice(0, code.len() - 1)) | ||||||
|  |     total += len * num | ||||||
|  |   } | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  | #show-puzzle( | ||||||
|  |   21, 1, | ||||||
|  |   solve, | ||||||
|  |   example: 126384 | ||||||
|  | ) | ||||||
							
								
								
									
										0
									
								
								src/day21/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/day21/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										61
									
								
								src/day22/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/day22/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let random(prev) = { | ||||||
|  |   let step(a, shift) = { | ||||||
|  |     let s = if shift < 0 { | ||||||
|  |       a.bit-rshift(-shift) | ||||||
|  |     } else { | ||||||
|  |       a.bit-lshift(shift) | ||||||
|  |     } | ||||||
|  |     return s.bit-xor(a).bit-and(0xffffff) | ||||||
|  |   } | ||||||
|  |   let b = step(prev, 6) | ||||||
|  |   let c = step(b, -5) | ||||||
|  |   let d = step(c, 11) | ||||||
|  |   return d | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let solve(input, steps: 1) = { | ||||||
|  |   let values = input.split("\n").map(int) | ||||||
|  |   let total = 0 | ||||||
|  |   for value in values { | ||||||
|  |     for _ in range(steps) { | ||||||
|  |       value = random(value) | ||||||
|  |     } | ||||||
|  |     total += value | ||||||
|  |   } | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let examples = () | ||||||
|  | #let results = ( | ||||||
|  |   15887950, | ||||||
|  |   16495136, | ||||||
|  |   527345, | ||||||
|  |   704524, | ||||||
|  |   1553684, | ||||||
|  |   12683156, | ||||||
|  |   11100544, | ||||||
|  |   12249484, | ||||||
|  |   7753432, | ||||||
|  |   5908254 | ||||||
|  | ) | ||||||
|  | #for (i, res) in results.enumerate() { | ||||||
|  |   examples.push(( | ||||||
|  |     result: res, | ||||||
|  |     args: (steps: i + 1) | ||||||
|  |   )) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   22, 1, | ||||||
|  |   solve.with(steps: 2000), | ||||||
|  |   example: examples, | ||||||
|  |   only-example: true | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | #show-result(18261820068) | ||||||
|  |  | ||||||
|  | //B = ((A << 6) ^ A) & 0xffffff\ | ||||||
|  | //C = ((B >> 5) ^ B) & 0xffffff\ | ||||||
|  | //D = ((C << 11) ^ C) & 0xffffff | ||||||
							
								
								
									
										0
									
								
								src/day22/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/day22/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										50
									
								
								src/day23/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/day23/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let links = input.split("\n") | ||||||
|  |  | ||||||
|  |   let links-dict = (:) | ||||||
|  |  | ||||||
|  |   let to-test = () | ||||||
|  |   for link in links { | ||||||
|  |     let (a, b) = link.split("-") | ||||||
|  |     if a not in links-dict { | ||||||
|  |       links-dict.insert(a, ()) | ||||||
|  |     } | ||||||
|  |     if b not in links-dict { | ||||||
|  |       links-dict.insert(b, ()) | ||||||
|  |     } | ||||||
|  |     links-dict.at(a).push(b) | ||||||
|  |     links-dict.at(b).push(a) | ||||||
|  |     if a.starts-with("t") { | ||||||
|  |       to-test.push(a) | ||||||
|  |     } | ||||||
|  |     if b.starts-with("t") { | ||||||
|  |       to-test.push(b) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let total = 0 | ||||||
|  |   let groups = () | ||||||
|  |   for comp1 in to-test.dedup() { | ||||||
|  |     for comp2 in links-dict.at(comp1) { | ||||||
|  |       for comp3 in links-dict.at(comp2) { | ||||||
|  |         if comp1 in links-dict.at(comp3) { | ||||||
|  |           let group = (comp1, comp2, comp3).sorted() | ||||||
|  |           if group not in groups { | ||||||
|  |             total += 1 | ||||||
|  |             groups.push(group) | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   23, 1, | ||||||
|  |   solve, | ||||||
|  |   example: 7 | ||||||
|  | ) | ||||||
							
								
								
									
										104
									
								
								src/day23/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/day23/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let bron-kerbosch(links, R, P, X) = { | ||||||
|  |   if P.len() == 0 and X.len() == 0 { | ||||||
|  |     return if R.len() > 2 { | ||||||
|  |       R.sorted() | ||||||
|  |     } else { | ||||||
|  |       none | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let longest-len = 0 | ||||||
|  |   let longest = none | ||||||
|  |   let to-visit = P | ||||||
|  |   for v in to-visit { | ||||||
|  |     let neighbors = links.at(v) | ||||||
|  |     let clique = bron-kerbosch( | ||||||
|  |       links, | ||||||
|  |       R + (v,), | ||||||
|  |       P.filter(n => n in neighbors), | ||||||
|  |       X.filter(n => n in neighbors) | ||||||
|  |     ) | ||||||
|  |     if clique != none { | ||||||
|  |       let l = clique.len() | ||||||
|  |       if longest == none or l > longest-len { | ||||||
|  |         longest = clique | ||||||
|  |         longest-len = l | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     let _ = P.remove(0) | ||||||
|  |     X.push(v) | ||||||
|  |   } | ||||||
|  |   return longest | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let bron-kerbosch2(links, R, P, X) = { | ||||||
|  |   if P.len() == 0 and X.len() == 0 { | ||||||
|  |     return if R.len() > 2 { | ||||||
|  |       R.sorted() | ||||||
|  |     } else { | ||||||
|  |       none | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let pivot = if P.len() != 0 { | ||||||
|  |     P.first() | ||||||
|  |   } else { | ||||||
|  |     X.first() | ||||||
|  |   } | ||||||
|  |   let pivot-neighbors = links.at(pivot) | ||||||
|  |   let longest-len = 0 | ||||||
|  |   let longest = none | ||||||
|  |   let to-visit = P.filter(n => n not in pivot-neighbors) | ||||||
|  |   for v in to-visit { | ||||||
|  |     let neighbors = links.at(v) | ||||||
|  |     let clique = bron-kerbosch2( | ||||||
|  |       links, | ||||||
|  |       R + (v,), | ||||||
|  |       P.filter(n => n in neighbors), | ||||||
|  |       X.filter(n => n in neighbors) | ||||||
|  |     ) | ||||||
|  |     if clique != none { | ||||||
|  |       let l = clique.len() | ||||||
|  |       if longest == none or l > longest-len { | ||||||
|  |         longest = clique | ||||||
|  |         longest-len = l | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     let _ = P.remove(P.position(n => n == v)) | ||||||
|  |     X.push(v) | ||||||
|  |   } | ||||||
|  |   return longest | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let links = input.split("\n") | ||||||
|  |  | ||||||
|  |   let links-dict = (:) | ||||||
|  |  | ||||||
|  |   let to-test = () | ||||||
|  |   for link in links { | ||||||
|  |     let (a, b) = link.split("-") | ||||||
|  |     if a not in links-dict { | ||||||
|  |       links-dict.insert(a, ()) | ||||||
|  |     } | ||||||
|  |     if b not in links-dict { | ||||||
|  |       links-dict.insert(b, ()) | ||||||
|  |     } | ||||||
|  |     links-dict.at(a).push(b) | ||||||
|  |     links-dict.at(b).push(a) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let clique = bron-kerbosch2(links-dict, (), links-dict.keys(), ()) | ||||||
|  |  | ||||||
|  |   return clique.join(",") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   23, 2, | ||||||
|  |   solve, | ||||||
|  |   example: "co,de,ka,ta", | ||||||
|  |   only-example: true | ||||||
|  | ) | ||||||
|  | #show-result("ab,al,cq,cr,da,db,dr,fw,ly,mn,od,py,uh") | ||||||
							
								
								
									
										78
									
								
								src/day24/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/day24/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let (inputs, gates) = input.split("\n\n") | ||||||
|  |   let ids = () | ||||||
|  |   inputs = inputs.split("\n").map(i => { | ||||||
|  |     let (id, value) = i.split(": ") | ||||||
|  |     return (id: id, value: value == "1") | ||||||
|  |   }) | ||||||
|  |   ids += inputs.map(i => i.id) | ||||||
|  |   gates = gates.split("\n").map(g => { | ||||||
|  |     let (gate, output) = g.split(" -> ") | ||||||
|  |     let (i1, op, i2) = gate.split(" ") | ||||||
|  |     return ( | ||||||
|  |       in1: i1, | ||||||
|  |       in2: i2, | ||||||
|  |       op: op, | ||||||
|  |       out: output | ||||||
|  |     ) | ||||||
|  |   }) | ||||||
|  |   let gates-by-id = (:) | ||||||
|  |   for gate in gates { | ||||||
|  |     gates-by-id.insert(gate.out, gate) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ids += gates.map(g => g.out) | ||||||
|  |   ids = ids.dedup() | ||||||
|  |   let dbg = (inputs, gates) | ||||||
|  |  | ||||||
|  |   let values = (:) | ||||||
|  |   for input in inputs { | ||||||
|  |     values.insert(input.id, input.value) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let stack = ids.filter(id => id.starts-with("z")) | ||||||
|  |   let output = (0,) * stack.len() | ||||||
|  |   while stack.len() != 0 { | ||||||
|  |     let v = stack.pop() | ||||||
|  |     if v in values { | ||||||
|  |       if v.starts-with("z") { | ||||||
|  |         let i = int(v.slice(1)) | ||||||
|  |         output.at(i) = int(values.at(v)) | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       stack.push(v) | ||||||
|  |       let gate = gates-by-id.at(v) | ||||||
|  |       if gate.in1 in values and gate.in2 in values { | ||||||
|  |         let v1 = values.at(gate.in1) | ||||||
|  |         let v2 = values.at(gate.in2) | ||||||
|  |         let value = if gate.op == "AND" { | ||||||
|  |           v1 and v2 | ||||||
|  |         } else if gate.op == "OR" { | ||||||
|  |           v1 or v2 | ||||||
|  |         } else if gate.op == "XOR" { | ||||||
|  |           (v1 or v2) and not (v1 and v2) | ||||||
|  |         } | ||||||
|  |         values.insert(v, value) | ||||||
|  |       } else { | ||||||
|  |         stack.push(gate.in1) | ||||||
|  |         stack.push(gate.in2) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let result = output.rev() | ||||||
|  |                      .fold(0, (a, b) => a.bit-lshift(1).bit-or(b)) | ||||||
|  |  | ||||||
|  |   return result | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   24, 1, | ||||||
|  |   solve, | ||||||
|  |   example: ( | ||||||
|  |     "1": 4, | ||||||
|  |     "2": 2024 | ||||||
|  |   ) | ||||||
|  | ) | ||||||
							
								
								
									
										0
									
								
								src/day24/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/day24/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										61
									
								
								src/day25/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/day25/puzzle1.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | #import "/src/utils.typ": * | ||||||
|  |  | ||||||
|  | #let parse-schematic(schematic) = { | ||||||
|  |   let lines = schematic.split("\n") | ||||||
|  |   let is-key = "." in schematic.first() | ||||||
|  |  | ||||||
|  |   let n-cols = lines.first().len() | ||||||
|  |   let n-rows = lines.len() | ||||||
|  |   let heights = () | ||||||
|  |  | ||||||
|  |   for x in range(n-cols) { | ||||||
|  |     let y = if is-key {n-rows - 2} else {1} | ||||||
|  |     let h = 0 | ||||||
|  |     for i in range(n-rows) { | ||||||
|  |       if lines.at(y).at(x) == "." { | ||||||
|  |         break | ||||||
|  |       } | ||||||
|  |       h += 1 | ||||||
|  |       y += if is-key {-1} else {1} | ||||||
|  |     } | ||||||
|  |     heights.push(h) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return (if is-key {"key"} else {"lock"}, heights) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let fits(lock, key) = { | ||||||
|  |   let tmp = lock.zip(key).map(p => p.sum()) | ||||||
|  |   return calc.max(..tmp) <= 5 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #let solve(input) = { | ||||||
|  |   let schematics = input.split("\n\n") | ||||||
|  |  | ||||||
|  |   let locks = () | ||||||
|  |   let keys = () | ||||||
|  |   for schematic in schematics { | ||||||
|  |     let (type, heights) = parse-schematic(schematic) | ||||||
|  |     if type == "key" { | ||||||
|  |       keys.push(heights) | ||||||
|  |     } else { | ||||||
|  |       locks.push(heights) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   let total = 0 | ||||||
|  |   for key in keys { | ||||||
|  |     for lock in locks { | ||||||
|  |       if fits(lock, key) { | ||||||
|  |         total += 1 | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return total | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #show-puzzle( | ||||||
|  |   25, 1, | ||||||
|  |   solve, | ||||||
|  |   example: 3 | ||||||
|  | ) | ||||||
							
								
								
									
										0
									
								
								src/day25/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/day25/puzzle2.typ
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										
											BIN
										
									
								
								src/main.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main.pdf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -197,8 +197,10 @@ | |||||||
|   set text(font: "Source Sans 3") |   set text(font: "Source Sans 3") | ||||||
|   set page( |   set page( | ||||||
|     footer: context { |     footer: context { | ||||||
|  |       if counter(page).get().first() != 1 { | ||||||
|         align(center, counter(page).display("1 / 1", both: true)) |         align(center, counter(page).display("1 / 1", both: true)) | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|   ) |   ) | ||||||
|   body |   body | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user