Compare commits
	
		
			5 Commits
		
	
	
		
			056e29b96c
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 93e365d10b | |||
| 9300d786f8 | |||
| ec75800078 | |||
| 16a0d9b3f8 | |||
| d830919adc | 
							
								
								
									
										
											BIN
										
									
								
								progress.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								progress.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 135 KiB | 
| @@ -41,4 +41,10 @@ | ||||
| 21: | ||||
|   stars: 0 | ||||
| 22: | ||||
|   stars: 1 | ||||
| 23: | ||||
|   stars: 2 | ||||
| 24: | ||||
|   stars: 1 | ||||
| 25: | ||||
|   stars: 1 | ||||
							
								
								
									
										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 @@ | ||||
| ##### | ||||
| .#### | ||||
| .#### | ||||
| .#### | ||||
| .#.#. | ||||
| .#... | ||||
| ..... | ||||
|  | ||||
| ##### | ||||
| ##.## | ||||
| .#.## | ||||
| ...## | ||||
| ...#. | ||||
| ...#. | ||||
| ..... | ||||
|  | ||||
| ..... | ||||
| #.... | ||||
| #.... | ||||
| #...# | ||||
| #.#.# | ||||
| #.### | ||||
| ##### | ||||
|  | ||||
| ..... | ||||
| ..... | ||||
| #.#.. | ||||
| ###.. | ||||
| ###.# | ||||
| ###.# | ||||
| ##### | ||||
|  | ||||
| ..... | ||||
| ..... | ||||
| ..... | ||||
| #.... | ||||
| #.#.. | ||||
| #.#.# | ||||
| ##### | ||||
							
								
								
									
										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.
										
									
								
							
		Reference in New Issue
	
	Block a user