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:
@ -1,12 +1,16 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
import copy
|
||||||
|
|
||||||
|
|
||||||
verbose = False
|
verbose = False
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
|
"""
|
||||||
|
Handles a map with obstacles and how a guard walks through it.
|
||||||
|
"""
|
||||||
|
|
||||||
directions = ["^", ">", "v", "<"]
|
directions = ["^", ">", "v", "<"]
|
||||||
#step_per_direction = [(0, -1), (1, 0), (0, 1), (-1, 0)]
|
|
||||||
step_per_direction = [(-1, 0), (0, 1), (1, 0), (0, -1)]
|
step_per_direction = [(-1, 0), (0, 1), (1, 0), (0, -1)]
|
||||||
|
|
||||||
class Tiles(Enum):
|
class Tiles(Enum):
|
||||||
@ -37,7 +41,7 @@ class Map:
|
|||||||
if verbose:
|
if verbose:
|
||||||
print("pos_in_map", pos)
|
print("pos_in_map", pos)
|
||||||
return pos[0] >= 0 and pos[0] < self.map.shape[0] \
|
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):
|
def look_ahead(self):
|
||||||
next_step = self.next_pos()
|
next_step = self.next_pos()
|
||||||
@ -97,9 +101,16 @@ class Map:
|
|||||||
self.pos = guards[0]
|
self.pos = guards[0]
|
||||||
self.trace.append(self.pos)
|
self.trace.append(self.pos)
|
||||||
self.direction = self.map[self.pos]
|
self.direction = self.map[self.pos]
|
||||||
# TODO: Use enum.
|
self.map[self.pos] = self.Tiles.FREE.value
|
||||||
#self.map[self.pos] = self.Tiles.FREE
|
|
||||||
self.map[self.pos] = "."
|
class LoopException(Exception):
|
||||||
|
"""
|
||||||
|
Gets thrown when the map results in the guard walking in an
|
||||||
|
infinite loop.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
"""
|
"""
|
||||||
@ -110,6 +121,9 @@ class Map:
|
|||||||
if verbose:
|
if verbose:
|
||||||
print("step.next_tile", next_tile)
|
print("step.next_tile", next_tile)
|
||||||
|
|
||||||
|
if self.is_stuck_in_loop():
|
||||||
|
raise self.LoopException()
|
||||||
|
|
||||||
if next_tile == self.Tiles.FREE:
|
if next_tile == self.Tiles.FREE:
|
||||||
# TODO: Really take a step! Do not only turn.
|
# TODO: Really take a step! Do not only turn.
|
||||||
self.pos = self.next_pos()
|
self.pos = self.next_pos()
|
||||||
@ -134,14 +148,48 @@ class Map:
|
|||||||
print(self.map[i][j], end="")
|
print(self.map[i][j], end="")
|
||||||
print()
|
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__":
|
if __name__ == "__main__":
|
||||||
m = Map()
|
m = Map()
|
||||||
#m.load_map("testinput")
|
#m.load_map("testinput")
|
||||||
m.load_map("input")
|
m.load_map("input")
|
||||||
|
|
||||||
|
loop_obstacles = []
|
||||||
|
|
||||||
while m.step():
|
while m.step():
|
||||||
if verbose:
|
if verbose:
|
||||||
print(m.pos, m.direction)
|
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()
|
#m.show()
|
||||||
#print(len(m.trace), m.trace)
|
#print(len(m.trace), m.trace)
|
||||||
print(len(set(m.trace)))
|
#print(len(set(m.trace)))
|
||||||
|
print(len(loop_obstacles))
|
||||||
|
|||||||
Reference in New Issue
Block a user