124 lines
3.0 KiB
Python
124 lines
3.0 KiB
Python
![]() |
import sys
|
||
|
sys.path.append('../aoclib')
|
||
|
|
||
|
from aoclib import Input
|
||
|
import re
|
||
|
from collections import defaultdict
|
||
|
|
||
|
class Robot:
|
||
|
def __init__(self, x, y, xv, yv: int):
|
||
|
self.x = x
|
||
|
self.y = y
|
||
|
self.xv = xv
|
||
|
self.yv = yv
|
||
|
|
||
|
def step(self, max_x, max_y, n=1):
|
||
|
for _ in range(n):
|
||
|
self.x = (self.x + self.xv) % max_x
|
||
|
self.y = (self.y + self.yv) % max_y
|
||
|
|
||
|
class Map:
|
||
|
def __init__(self, x, y: int, robots: list[Robot]):
|
||
|
self.x = x
|
||
|
self.y = y
|
||
|
self.robots = robots
|
||
|
self.steps = 0
|
||
|
|
||
|
def __str__(self):
|
||
|
field = [[0 for _ in range(self.x)] for _ in range(self.y)]
|
||
|
for r in self.robots:
|
||
|
field[r.y][r.x] += 1
|
||
|
return '\n'.join(''.join('*' if x>0 else ' ' for x in l) for l in field)
|
||
|
|
||
|
def step(self, n=1):
|
||
|
for r in self.robots:
|
||
|
r.step(self.x, self.y, n)
|
||
|
self.steps += n
|
||
|
|
||
|
def solve1(self) -> int:
|
||
|
self.step(100)
|
||
|
_x, _y = self.x // 2, self.y // 2
|
||
|
field = [[0 for _ in range(self.x)] for _ in range(self.y)]
|
||
|
for r in self.robots:
|
||
|
field[r.y][r.x] += 1
|
||
|
|
||
|
q1 = 0
|
||
|
for y in range(0, _y):
|
||
|
for x in range(0, _x):
|
||
|
q1 += field[y][x]
|
||
|
|
||
|
q2 = 0
|
||
|
for y in range(0, _y):
|
||
|
for x in range(_x+1, len(field[0])):
|
||
|
q2 += field[y][x]
|
||
|
|
||
|
q3 = 0
|
||
|
for y in range(_y+1, len(field)):
|
||
|
for x in range(0, _x):
|
||
|
q3 += field[y][x]
|
||
|
|
||
|
q4 = 0
|
||
|
for y in range(_y+1, len(field)):
|
||
|
for x in range(_x+1, len(field[0])):
|
||
|
q4 += field[y][x]
|
||
|
|
||
|
return q1*q2*q3*q4
|
||
|
|
||
|
def solve2(self) -> int:
|
||
|
while not self.has_n_adjacent(20):
|
||
|
self.step()
|
||
|
return self.steps
|
||
|
|
||
|
|
||
|
def has_n_adjacent(self, n=10):
|
||
|
d = defaultdict(set)
|
||
|
for r in self.robots:
|
||
|
d[r.x].add(r.y)
|
||
|
|
||
|
def search(l, n):
|
||
|
for i in range(len(l) - n):
|
||
|
if l[i+n-1] - l[i] == n-1:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
for x in d:
|
||
|
l = sorted(list(d[x]))
|
||
|
if search(l, n):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
def parse_input(lines: list[str], x, y: int):
|
||
|
rrx = re.compile(r'p=(\d+),(\d+) v=(-*\d+),(-*\d+)')
|
||
|
robots = list()
|
||
|
for l in lines:
|
||
|
m = rrx.search(l)
|
||
|
r = Robot(int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)))
|
||
|
robots.append(r)
|
||
|
|
||
|
m = Map(x, y, robots)
|
||
|
return m
|
||
|
|
||
|
def solve1(lines: list[str]):
|
||
|
#m = parse_input(lines, 11, 7)
|
||
|
m = parse_input(lines, 101, 103)
|
||
|
return m.solve1()
|
||
|
|
||
|
|
||
|
def solve2(lines: list[str]):
|
||
|
m = parse_input(lines, 101, 103)
|
||
|
m.solve2()
|
||
|
print(m)
|
||
|
return m.steps
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
#lines = Input('input_test.txt').lines()
|
||
|
lines = Input('input.txt').lines()
|
||
|
|
||
|
#part 1
|
||
|
print('part 1:', solve1(lines)) # 27157
|
||
|
|
||
|
#part 2
|
||
|
print('part 2:', solve2(lines)) # 8258
|