diff --git a/day3.py b/day3.py new file mode 100644 index 0000000..c7658d6 --- /dev/null +++ b/day3.py @@ -0,0 +1,94 @@ +puzzle_input = 0 # TODO + +def cardinals(distance): + d = 0 + distance[1] = d + yield 1 + + d += 1 + distance[2] = d + yield 2 + + while True: + v = (2*d)**2 - (d-1) + distance[v] = d + yield v + + v = (2*d)**2 + (d+1) + distance[v] = d + yield v + + v = (2*d + 1)**2 - d + distance[v] = d + yield v + + v = (2*d + 1)**2 + (d+1) + distance[v] = d + 1 + yield v + + d += 1 + +def closest_cardinals(n, distance): + cs = cardinals(distance) + lo = next(cs) + hi = next(cs) + while not lo <= n <= hi: + lo, hi = hi, next(cs) + return lo, hi + +def manhattan_to_center(n): + distance = {} + best = sorted(closest_cardinals(n, distance), key=lambda x: abs(n - x))[0] + return distance[best] + abs(n - best) + +for inp, expected in [ + (1, 0), + (2, 1), + (12, 3), + (23, 2), + (1024, 31), +]: + actual = manhattan_to_center(inp) + assert actual == expected, f'Expected {expected} got {actual}' + +print(manhattan_to_center(puzzle_input)) + +def walking_order(): + start = (0, 0) + R, D, L, U = [(+1, 0), (0, -1), (-1, 0), (0, +1)] + + yield R + yield U + + count = 2 + while True: + for deltas in [(L, D), (R, U)]: + for delta in deltas: + for _ in range(count): + yield delta + count += 1 + +def neighbors(cell): + x, y = cell + for dx in range(-1, 2): + for dy in range(-1, 2): + if dx == dy == 0: continue + yield (x+dx, y+dy) + +def sum_neighbors_until(limit): + grid = {} + deltas = walking_order() + + cell = (0, 0) + grid[cell] = 1 + + while True: + x, y = cell + dx, dy = next(deltas) + cell = (x+dx, y+dy) + value = sum(grid.get(n, 0) for n in neighbors(cell)) + grid[cell] = value + if value > limit: + return value + +print(sum_neighbors_until(puzzle_input))