Explorar o código

Solve 2016 day 12-15

Taddeus Kroes %!s(int64=6) %!d(string=hai) anos
pai
achega
6159ebd589
Modificáronse 6 ficheiros con 189 adicións e 0 borrados
  1. 41 0
      2016/12_assembunny.py
  2. 50 0
      2016/13_cubicles.py
  3. 43 0
      2016/14_otp.py
  4. 26 0
      2016/15_discs.py
  5. 23 0
      2016/input/12
  6. 6 0
      2016/input/15

+ 41 - 0
2016/12_assembunny.py

@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+import sys
+
+def read_program(f):
+    maybe_int = lambda x: int(x) if x.isdigit() or x[0] == '-' else x
+    for line in f:
+        yield tuple(map(maybe_int, line.split()))
+
+def run(p, init):
+    regs = [0, 0, init, 0]
+    pc = 0
+
+    def load(x):
+        return x if isinstance(x, int) else regs[ord(x) - ord('a')]
+
+    def store(reg, value):
+        regs[ord(reg) - ord('a')] = value
+
+    while pc < len(p):
+        instr = p[pc]
+        opcode = instr[0]
+        if opcode == 'cpy':
+            src, dst = instr[1:]
+            store(dst, load(src))
+        elif opcode == 'inc':
+            reg = instr[1]
+            store(reg, load(reg) + 1)
+        elif opcode == 'dec':
+            reg = instr[1]
+            store(reg, load(reg) - 1)
+        elif opcode == 'jnz':
+            pred, offset = instr[1:]
+            if load(pred):
+                pc += load(offset) - 1
+        pc += 1
+
+    return regs[0]
+
+program = list(read_program(sys.stdin))
+print(run(program, 0))
+print(run(program, 1))

+ 50 - 0
2016/13_cubicles.py

@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+from heapq import heappush, heappop
+
+magic = 1350
+
+def popcount(n):
+    count = 0
+    while n:
+        count += n & 1
+        n >>= 1
+    return count
+
+def is_space(x, y):
+    return not popcount(x*x + 3*x + 2*x*y + y + y*y + magic) % 2
+
+def neighboring_spaces(x, y):
+    if is_space(x + 1, y):
+        yield x + 1, y
+    if is_space(x, y + 1):
+        yield x, y + 1
+    if x > 0 and is_space(x - 1, y):
+        yield x - 1, y
+    if y > 0 and is_space(x, y - 1):
+        yield x, y - 1
+
+def uniform_cost_search(source):
+    frontier = [(0, source)]
+    explored = {source}
+    while frontier:
+        dist, u = heappop(frontier)
+        yield u, dist
+        for v in neighboring_spaces(*u):
+            if v not in explored:
+                heappush(frontier, (dist + 1, v))
+                explored.add(v)
+
+def shortest_path(source, dest):
+    for node, dist in uniform_cost_search(source):
+        if node == dest:
+            return dist
+
+def reachable_in(source, maxdist):
+    count = 0
+    for node, dist in uniform_cost_search(source):
+        if dist > maxdist:
+            return count
+        count += 1
+
+print(shortest_path((1, 1), (31, 39)))
+print(reachable_in((1, 1), 50))

+ 43 - 0
2016/14_otp.py

@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+from hashlib import md5
+from itertools import count
+
+def digest(index, salt, iters):
+    hashed = salt + str(index)
+    while iters > 0:
+        hashed = md5(hashed.encode('ascii')).hexdigest()
+        iters -= 1
+    return hashed
+
+def key_indices(salt, stretch):
+    candidates = {}
+    for index in count(0):
+        conseq = prev = None
+        three = None
+        fives = set()
+
+        for cur in digest(index, salt, stretch + 1):
+            if cur == prev:
+                conseq += 1
+                if conseq == 3 and three is None:
+                    three = cur
+                elif conseq == 5:
+                    fives.add(cur)
+            else:
+                conseq = 1
+            prev = cur
+
+        for five in fives:
+            for candidate in candidates.pop(five, []):
+                if index - candidate <= 1000:
+                    yield candidate
+        if three:
+            candidates.setdefault(three, []).append(index)
+
+def nth_key(n, salt, stretch):
+    gen_keys = key_indices(salt, stretch)
+    return max(next(gen_keys) for i in range(64))
+
+salt = 'cuanljph'
+print(nth_key(64, salt, 0))
+print(nth_key(64, salt, 2016))

+ 26 - 0
2016/15_discs.py

@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+import re
+import sys
+
+def parse(f):
+    for i, line in enumerate(f):
+        nr, size, time, pos = map(int, re.findall(r'\d+', line))
+        assert nr == i + 1
+        assert time == 0
+        yield size, pos
+
+def is_range(seq):
+    return all(seq[i] - seq[i - 1] == 1 for i in range(1, len(seq)))
+
+def button_time(discs):
+    sizes, positions = zip(*discs)
+    desired = tuple(-(delay + 1) % size for delay, size in enumerate(sizes))
+    time = 0
+    while positions != desired:
+        positions = tuple((p + 1) % s for s, p in zip(sizes, positions))
+        time += 1
+    return time
+
+discs = list(parse(sys.stdin))
+print(button_time(discs))
+print(button_time(discs + [(11, 0)]))

+ 23 - 0
2016/input/12

@@ -0,0 +1,23 @@
+cpy 1 a
+cpy 1 b
+cpy 26 d
+jnz c 2
+jnz 1 5
+cpy 7 c
+inc d
+dec c
+jnz c -2
+cpy a c
+inc a
+dec b
+jnz b -2
+cpy c b
+dec d
+jnz d -6
+cpy 13 c
+cpy 14 d
+inc a
+dec d
+jnz d -2
+dec c
+jnz c -5

+ 6 - 0
2016/input/15

@@ -0,0 +1,6 @@
+Disc #1 has 17 positions; at time=0, it is at position 15.
+Disc #2 has 3 positions; at time=0, it is at position 2.
+Disc #3 has 19 positions; at time=0, it is at position 4.
+Disc #4 has 13 positions; at time=0, it is at position 2.
+Disc #5 has 7 positions; at time=0, it is at position 2.
+Disc #6 has 5 positions; at time=0, it is at position 0.