#!/usr/bin/env python # coding: utf-8 # In[1]: import aocd inputvalue = int(aocd.get_data(day=3, year=2017)) # In[2]: 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) # In[3]: 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()))