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 |
@ -33,4 +33,18 @@
|
||||
17:
|
||||
stars: 1
|
||||
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,7 +197,9 @@
|
||||
set text(font: "Source Sans 3")
|
||||
set page(
|
||||
footer: context {
|
||||
align(center, counter(page).display("1 / 1", both: true))
|
||||
if counter(page).get().first() != 1 {
|
||||
align(center, counter(page).display("1 / 1", both: true))
|
||||
}
|
||||
}
|
||||
)
|
||||
body
|
||||
|
Reference in New Issue
Block a user