summary refs log tree commit diff
path: root/22.23
diff options
context:
space:
mode:
Diffstat (limited to '22.23')
-rw-r--r--22.23/part1.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/22.23/part1.py b/22.23/part1.py
new file mode 100644
index 0000000..818e7ed
--- /dev/null
+++ b/22.23/part1.py
@@ -0,0 +1,65 @@
+from sys import stdin
+
+elves = set()
+for y, line in enumerate(stdin):
+    for x, c in enumerate(line):
+        if c == '#':
+            elves.add((x, y))
+
+def tadd(a, b):
+    return tuple(map(sum, zip(a, b)))
+
+def move(elf, elves, phase):
+    def singlemove(phase):
+        phase = phase % 4
+        d = None
+        if phase == 0: d = (0, -1)
+        if phase == 1: d = (0, +1)
+        if phase == 2: d = (-1, 0)
+        if phase == 3: d = (+1, 0)
+
+        colls = []
+        for n in [-1, 0, 1]:
+            v = list(d)
+            v[v.index(0)] = n
+            v = tadd(elf, v)
+            if v in elves:
+                return None
+        return tadd(elf, d)
+
+    def crowded():
+        for dx in [-1, 0, 1]:
+            for dy in [-1, 0, 1]:
+                if dx == dy == 0: continue
+                if tadd(elf, (dx, dy)) in elves: return True
+        return False
+    if not crowded():
+        return elf
+
+    for i in range(4):
+        r = singlemove(phase + i)
+        if r: return r
+    return elf
+
+def step(elves, phase):
+    goals = set()
+    dupes = set()
+    after = set()
+    for elf in elves:
+        g = move(elf, elves, phase)
+        if g in goals:
+            dupes.add(g)
+        else:
+            goals.add(g)
+    for elf in elves:
+        g = move(elf, elves, phase)
+        after.add(elf if g in dupes else g)
+    return after
+
+for i in range(10):
+    elves = step(elves, i)
+
+xs = [t[0] for t in elves]
+ys = [t[1] for t in elves]
+score = (max(xs) - min(xs) + 1) * (max(ys) - min(ys) + 1) - len(elves)
+print(score)