import aocd
inputvalue = int(aocd.get_data(day=3, year=2017))
import math
def spiraldistance(pos):
if pos == 1:
return 0
prev = int(math.sqrt(pos))
if prev % 2 == 0:
prev -= 1
sidelength = prev + 1
offset = (pos - (prev**2)) % sidelength
middle = sidelength // 2
return middle + abs(middle - offset)
tests = {1: 0, 12: 3, 23: 2, 1024: 31}
for pos, expected in tests.items():
assert (
spiraldistance(pos) == expected
), f"spiraldistance({pos}) => {spiraldistance(pos)}, not {expected}"
spiraldistance(inputvalue)
430
from itertools import count, cycle, islice, product
def summed_larger():
grid = {(0, 0): 1}
directions = tuple((x, y) for x, y in product((-1, 0, 1), repeat=2) if x or y)
steps = cycle([(0, 1), (-1, 0), (0, -1), (1, 0)])
step = next(steps)
x, y = 1, 0
size = 3
yield 1
for num in count(2):
value = sum(grid.get((x + dx, y + dy), 0) for dx, dy in directions)
yield value
grid[(x, y)] = value
if num == size**2: # next spiral ring
size += 2
x += 1
step = next(steps)
else:
if (num - ((size - 2) ** 2)) % (size - 1) == 0: # change direction
step = next(steps)
x += step[0]
y += step[1]
print(list(islice(summed_larger(), 25)))
next(filter(lambda v: v > inputvalue, summed_larger()))
[1, 1, 2, 4, 5, 10, 11, 23, 25, 26, 54, 57, 59, 122, 133, 142, 147, 304, 330, 351, 362, 747, 806, 880, 931]
312453