advent/2018/11.py

113 lines
3.4 KiB
Python
Raw Normal View History

2018-12-12 00:28:18 +00:00
class Grid:
def __init__(self, serial):
self.serial = serial
2018-12-12 06:23:03 +00:00
self.cells = []
self.populate()
2018-12-12 00:28:18 +00:00
def populate(self):
for y in range(1, 301):
self.cells.append([])
for x in range(1, 301):
2018-12-12 06:23:03 +00:00
self.cells[y - 1].append([])
2018-12-12 00:28:18 +00:00
power = self.cell_power(x, y)
self.set(x, y, power)
def get(self, x, y):
return self.cells[y - 1][x - 1]
def set(self, x, y, value):
self.cells[y - 1][x - 1] = value
2018-12-12 06:23:03 +00:00
def cell_power(self, x, y):
2018-12-12 00:28:18 +00:00
rack = x + 10
p = (rack * y + self.serial) * rack
p = (p // 100) % 10 # keep only hundreds digit
return p - 5
class Cursor:
2018-12-13 00:33:01 +00:00
def __init__(self, parent_grid, cursor_size):
2018-12-12 00:28:18 +00:00
self.grid = parent_grid
2018-12-13 00:33:01 +00:00
self.size = cursor_size
2018-12-12 00:28:18 +00:00
self.x = self.y = 1
2018-12-13 00:33:01 +00:00
self.total_power = self.calc_power()
2018-12-12 00:28:18 +00:00
def step(self, direction):
2018-12-12 06:23:03 +00:00
if direction in ('right', 'left'):
axis = 'vertical'
2018-12-13 00:33:01 +00:00
delta_x, delta_y = 1, 0
2018-12-12 06:23:03 +00:00
elif direction in ('up', 'down'):
axis = 'horizontal'
2018-12-13 00:33:01 +00:00
delta_x, delta_y = 0, 1
2018-12-12 06:23:03 +00:00
if direction in ('right', 'down'):
2018-12-13 00:33:01 +00:00
offset_new, offset_old = self.size, 0
2018-12-12 06:23:03 +00:00
elif direction in ('left', 'up'):
2018-12-13 00:33:01 +00:00
offset_new, offset_old = -1, self.size - 1
delta_x, delta_y = delta_x * -1, delta_y * -1
2018-12-12 06:23:03 +00:00
2018-12-13 00:33:01 +00:00
new_points = self.get_row(offset_new, axis)
old_points = self.get_row(offset_old, axis)
2018-12-12 06:23:03 +00:00
self.total_power += sum(new_points)
self.total_power -= sum(old_points)
2018-12-13 00:33:01 +00:00
self.x, self.y = self.x + delta_x, self.y + delta_y
2018-12-12 06:23:03 +00:00
def get_row(self, delta, axis):
points = []
if axis == 'vertical':
2018-12-13 00:33:01 +00:00
for y in range(self.y, self.y + self.size):
2018-12-12 06:23:03 +00:00
points.append(self.grid.get(self.x + delta, y))
elif axis == 'horizontal':
2018-12-13 00:33:01 +00:00
for x in range(self.x, self.x + self.size):
2018-12-12 06:23:03 +00:00
points.append(self.grid.get(x, self.y + delta))
return points
2018-12-12 00:28:18 +00:00
2018-12-12 06:23:03 +00:00
def jump(self, x, y):
self.x = x
self.y = y
2018-12-13 00:33:01 +00:00
self.total_power = self.calc_power()
2018-12-12 06:23:03 +00:00
def calc_power(self):
2018-12-13 00:33:01 +00:00
total = 0
for y in range(self.size):
for x in range(self.size):
total += self.grid.get(self.x + x, self.y + y)
return total
2018-12-12 00:28:18 +00:00
2018-12-12 06:23:03 +00:00
def find_max(self):
coords, max_power = (0, 0), 0
prev_dir = 'down'
2018-12-12 00:28:18 +00:00
while True:
if self.total_power > max_power:
2018-12-12 06:23:03 +00:00
coords, max_power = (self.x, self.y), self.total_power
2018-12-13 00:33:01 +00:00
if self.x in (1, 301 - self.size) and prev_dir != 'down': # cursor is at edge of grid
2018-12-12 06:23:03 +00:00
direction = 'down'
elif self.y % 2 == 0: # go left on even lines
direction = 'left'
else: # go right on odd lines
direction = 'right'
prev_dir = direction
try:
self.step(direction)
except IndexError:
break
return coords, max_power
2018-12-12 00:28:18 +00:00
2018-12-12 06:23:03 +00:00
grid = Grid(7857)
2018-12-13 00:33:01 +00:00
cursor = Cursor(grid, 3)
2018-12-12 06:23:03 +00:00
coords, max_power = cursor.find_max()
2018-12-13 00:33:01 +00:00
print(f'Part 1: {coords[0]},{coords[1]}, ({max_power})\n')
coords = max_power = grid_size = 0
for s in range(1, 301):
cursor = Cursor(grid, s)
c, m = cursor.find_max()
if m > max_power:
coords, max_power, grid_size = c, m, s
print(f'Part 2: {coords[0]},{coords[1]},{grid_size} ({max_power})\n')