class Walker: def __init__(self): self.x = 0 self.y = 0 self.address = 1 self.current_radius = 0 self.cells = {(0, 0): 1} def right(self): self.x += 1 self.address += 1 def left(self): self.x -= 1 self.address += 1 def up(self): self.y += 1 self.address += 1 def down(self): self.y -= 1 self.address += 1 def walk(self): # check if time to switch bands if self.x == self.current_radius and self.y == -1 * self.current_radius: self.right() self.current_radius += 1 self.populate_cell() return # figure out side and move accordingly if abs(self.y) < self.current_radius: # left or right if self.x > 0: # right self.up() else: # left self.down() elif abs(self.x) < self.current_radius: # top or bottom if self.y > 0: # top self.left() else: # bottom self.right() else: # corner if self.x > 0 and self.y > 0: # top right self.left() elif self.x < 0 and self.y > 0: # top left self.down() elif self.x < 0 and self.y < 0: # bottom left self.right() elif self.x > 0 and self.y < 0: # bottom right self.up() self.populate_cell() def populate_cell(self): total = 0 for dx in 1, 0, -1: for dy in 1, 0, -1: if dx != 0 or dy != 0: coords = (self.x + dx, self.y + dy) total += self.cells.get(coords, 0) self.cells[self.x, self.y] = total def test(self, steps=1): for i in range(steps): self.walk() self.display() def display(self): print('Address:', self.address) print('Value:', self.cells[self.x, self.y]) print(f'Position: ({self.x}, {self.y})') print('Radius:', self.current_radius) if __name__ == '__main__': n = 325489 walker = Walker() ''' # part 1 while walker.address < n: walker.walk() walker.display() print('Distance:', abs(walker.x) + abs(walker.y)) ''' # part 2 while walker.cells[walker.x, walker.y] <= n: walker.walk() walker.display()