2024(6): try part 2

* My code is way too slow.
* I should put the obstacle in the path before starting the walk, as it
  could be that the obstacle is ran into earlier.
This commit is contained in:
2024-12-26 11:35:43 +01:00
parent d515a7b0c0
commit 1a7f6304ee

View File

@ -1,12 +1,16 @@
import numpy as np
from enum import Enum
import copy
verbose = False
class Map:
"""
Handles a map with obstacles and how a guard walks through it.
"""
directions = ["^", ">", "v", "<"]
#step_per_direction = [(0, -1), (1, 0), (0, 1), (-1, 0)]
step_per_direction = [(-1, 0), (0, 1), (1, 0), (0, -1)]
class Tiles(Enum):
@ -37,7 +41,7 @@ class Map:
if verbose:
print("pos_in_map", pos)
return pos[0] >= 0 and pos[0] < self.map.shape[0] \
and pos[1] >= 0 and pos[0] < self.map.shape[1]
and pos[1] >= 0 and pos[1] < self.map.shape[1]
def look_ahead(self):
next_step = self.next_pos()
@ -97,9 +101,16 @@ class Map:
self.pos = guards[0]
self.trace.append(self.pos)
self.direction = self.map[self.pos]
# TODO: Use enum.
#self.map[self.pos] = self.Tiles.FREE
self.map[self.pos] = "."
self.map[self.pos] = self.Tiles.FREE.value
class LoopException(Exception):
"""
Gets thrown when the map results in the guard walking in an
infinite loop.
"""
pass
def step(self):
"""
@ -110,6 +121,9 @@ class Map:
if verbose:
print("step.next_tile", next_tile)
if self.is_stuck_in_loop():
raise self.LoopException()
if next_tile == self.Tiles.FREE:
# TODO: Really take a step! Do not only turn.
self.pos = self.next_pos()
@ -134,14 +148,48 @@ class Map:
print(self.map[i][j], end="")
print()
def is_stuck_in_loop(self):
"""
Returns whether the guard is stuck in loop.
This only happens when enough steps are taken. Currently, it
checks whether the current position is already part of the trace
at least four times, so that it has travelled the position at
least twice from at least one direction.
"""
return self.trace.count(self.pos) > 4
def copy(self):
if verbose:
print(f"Deep copying")
return copy.deepcopy(self)
if __name__ == "__main__":
m = Map()
#m.load_map("testinput")
m.load_map("input")
loop_obstacles = []
while m.step():
if verbose:
print(m.pos, m.direction)
# Create a copy
forked_map = m.copy()
forked_map.map[forked_map.next_pos()] = Map.Tiles.OBSTACLE.value
print(f"Forking at {forked_map.next_pos()}... ", end="")
try:
while forked_map.step():
continue
except Map.LoopException:
print("loop.")
loop_obstacles.append(m.next_pos())
else:
print("no loop")
#m.show()
#print(len(m.trace), m.trace)
print(len(set(m.trace)))
#print(len(set(m.trace)))
print(len(loop_obstacles))