add day 6 part 2

This commit is contained in:
Dmitry Fedotov
2024-12-15 12:45:53 +03:00
parent 0f2951b9e1
commit 028470c93e
2 changed files with 65 additions and 17 deletions

View File

@@ -35,6 +35,9 @@ class Guard(object):
def next(self): def next(self):
self.x, self.y = self.want() self.x, self.y = self.want()
def copy(self):
return Guard(self.x, self.y, self.d)
def __str__(self): def __str__(self):
return self.d return self.d
@@ -50,38 +53,77 @@ class Map(list):
def out_of_bounds(self, x, y): def out_of_bounds(self, x, y):
return (x < 0 or y < 0) or (x >= len(self[0]) or y >= len(self)) return (x < 0 or y < 0) or (x >= len(self[0]) or y >= len(self))
def copy(self):
return Map([l.copy() for l in self])
class Lab(object): class Lab(object):
def __init__(self, m: Map, g: Guard): def __init__(self, m: Map, g: Guard):
self.m = m self.m = m.copy()
self.g = g self.g = g.copy()
self.visited = set() self.visited = set()
self.cycles = set()
self.g_init = g
self.m_init = m
self.print_visited = False self.print_visited = False
self.g_init = Guard(g.x, g.y, g.d)
def next(self) -> bool: def next(self) -> (bool, bool):
self.visited.add(self.g.curr()) self.visited.add(self.g.curr())
x, y = self.g.want() x, y = self.g.want()
if self.m.out_of_bounds(x, y): if self.m.out_of_bounds(x, y):
return False return False, False
elif self.m.has_obstacle(x, y): elif self.m.has_obstacle(x, y):
_x, _y = self.g.curr()
t = (self.g.d, _x, _y)
if t in self.cycles:
# approached same obstacle
# from same direction
return False, True
self.cycles.add(t)
self.g.turn() self.g.turn()
return True return True, False
self.g.next() self.g.next()
return True return True, False
def reset(self): def _reset(self):
self.visited = set() self.visited = set()
self.g = Guard(self.g_init.x, self.g_init.y, self.g_init.d) self.cycles = set()
self.g = self.g_init.copy()
self.m = self.m_init.copy()
def solve_part1(self): def solve_part1(self) -> int:
while self.next(): self._reset()
pass while True:
ok, _ = self.next()
if not ok:
break
return len(self.visited) return len(self.visited)
def solve_part2(self) -> int:
self.solve_part1() # just filling visited
visited = self.visited.copy()
cycle_count = 0
for t in visited:
if self._try_cycle(t):
cycle_count += 1
return cycle_count
def _try_cycle(self, t: tuple[int]) -> bool:
self._reset()
x, y = t
self.m[y][x] = '#'
while True:
ok, cycled = self.next()
if cycled:
return True
if not ok:
return False
def animate(self, visited=False): def animate(self, visited=False):
''' '''
Just wanted to show kids what it looks like Just wanted to show kids what it looks like
@@ -98,6 +140,7 @@ class Lab(object):
while self.next(): while self.next():
cls() cls()
print(self) print(self)
print(self.cycles)
sleep(0.5) sleep(0.5)
def __str__(self): def __str__(self):
@@ -122,17 +165,16 @@ def parse_input(lst) -> (Lab):
if __name__ == '__main__': if __name__ == '__main__':
lines = Input('input_test.txt').lines_as_lists() #lines = Input('input_test.txt').lines_as_lists()
#lines = Input('input.txt').lines_as_lists() lines = Input('input.txt').lines_as_lists()
lab = parse_input(lines) lab = parse_input(lines)
#lab.animate(True) #lab.animate(True)
lab.animate() #lab.animate()
lab.reset()
#part 1 #part 1
print('part 1:', lab.solve_part1()) print('part 1:', lab.solve_part1())
#part 2 #part 2
print('part 2:', '') print('part 2:', lab.solve_part2())

View File

@@ -178,3 +178,9 @@ Option six, put a tank of sovereign glue right next to the tank of universal sol
It doesn't really matter what you choose to use as an obstacle so long as you and The Historians can put it into position without the guard noticing. The important thing is having enough options that you can find one that minimizes time paradoxes, and in this example, there are 6 different positions you could choose. It doesn't really matter what you choose to use as an obstacle so long as you and The Historians can put it into position without the guard noticing. The important thing is having enough options that you can find one that minimizes time paradoxes, and in this example, there are 6 different positions you could choose.
You need to get the guard stuck in a loop by adding a single new obstruction. How many different positions could you choose for this obstruction? You need to get the guard stuck in a loop by adding a single new obstruction. How many different positions could you choose for this obstruction?
Your puzzle answer was 1711.
Both parts of this puzzle are complete! They provide two gold stars: **