2024(6): solve part 1
The code is quite long lol. Also, the output is too verbose, but mwe!
This commit is contained in:
144
2024/06/part1.py
144
2024/06/part1.py
@ -1,15 +1,143 @@
|
||||
import numpy as np
|
||||
from enum import Enum
|
||||
|
||||
|
||||
def load_map(filename="input"):
|
||||
with open(filename, "r") as fp:
|
||||
data = fp.read
|
||||
|
||||
'''
|
||||
idee:
|
||||
sla ook het kleine voorbeeld op
|
||||
lees data in
|
||||
maak object "kaart"
|
||||
maak op object
|
||||
show() (prints map to screen)
|
||||
guard_directions = ["^", ">", "v", "<"]
|
||||
guard_path = [] # list of tuples (x, y)
|
||||
'''
|
||||
|
||||
class Map:
|
||||
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):
|
||||
BORDER = "+"
|
||||
FREE = "."
|
||||
OBSTACLE = "#"
|
||||
|
||||
def __init__(self):
|
||||
self.trace = []
|
||||
self.pos = None
|
||||
self.direction = None
|
||||
|
||||
def next_pos(self):
|
||||
"""
|
||||
Returns next position given the state of this Map.
|
||||
"""
|
||||
|
||||
next_pos = tuple([self.pos[i] + self.step_per_direction[self.directions.index(self.direction)][i] for i in range(len(self.pos))])
|
||||
print("next_pos", next_pos)
|
||||
return next_pos
|
||||
|
||||
def pos_in_map(self, pos):
|
||||
"""
|
||||
Returns whether pos is in the map.
|
||||
"""
|
||||
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]
|
||||
|
||||
def look_ahead(self):
|
||||
next_step = self.next_pos()
|
||||
print("look_ahead.next_step", next_step)
|
||||
if not self.pos_in_map(next_step):
|
||||
return self.Tiles.BORDER
|
||||
if self.map[*next_step] == "#":
|
||||
return self.Tiles.OBSTACLE
|
||||
if self.map[*next_step] == ".":
|
||||
return self.Tiles.FREE
|
||||
|
||||
def next_direction(self, direction: str):
|
||||
"""
|
||||
Return the direction turning right given direction.
|
||||
"""
|
||||
|
||||
assert direction in self.directions, "Invalid direction given"
|
||||
|
||||
if self.directions[-1] == direction:
|
||||
return self.directions[0]
|
||||
else:
|
||||
return self.directions[self.directions.index(direction) + 1]
|
||||
|
||||
def seek_guard_in_map(self):
|
||||
"""
|
||||
Looks for the guard in the map and returns its position.
|
||||
|
||||
Will raise an exception if multiple or none are found.
|
||||
"""
|
||||
|
||||
guard_locations = []
|
||||
for direction in self.directions:
|
||||
guard_locations.extend(list(zip(*np.where(m.map == direction))))
|
||||
return guard_locations
|
||||
|
||||
def load_map(self, filename="input"):
|
||||
"""
|
||||
Reads a map from a file without verifying its contents.
|
||||
"""
|
||||
|
||||
with open(filename, "r") as fp:
|
||||
data = fp.read().splitlines()
|
||||
chararray = np.array(data, dtype=str)\
|
||||
.view("U1")\
|
||||
.reshape((len(data), -1))
|
||||
self.map = chararray
|
||||
|
||||
# Find the location of the guard in the map.
|
||||
guards = self.seek_guard_in_map()
|
||||
print(guards)
|
||||
assert len(guards) == 1, "There should only be one guard in the map."
|
||||
|
||||
print(guards)
|
||||
self.pos = guards[0]
|
||||
self.trace.append(self.pos)
|
||||
self.direction = m.map[self.pos]
|
||||
# TODO: Use enum.
|
||||
#self.map[self.pos] = self.Tiles.FREE
|
||||
self.map[self.pos] = "."
|
||||
|
||||
def step(self):
|
||||
"""
|
||||
Take a step, turn or stop.
|
||||
"""
|
||||
|
||||
next_tile = self.look_ahead()
|
||||
print("step.next_tile", next_tile)
|
||||
|
||||
if next_tile == self.Tiles.FREE:
|
||||
self.pos = self.next_pos()
|
||||
self.trace.append(self.pos)
|
||||
return True
|
||||
elif next_tile == self.Tiles.OBSTACLE:
|
||||
self.direction = self.next_direction(self.direction)
|
||||
return True
|
||||
elif next_tile == self.Tiles.BORDER:
|
||||
return False
|
||||
|
||||
assert False, "Should not come here :')"
|
||||
|
||||
def show(self):
|
||||
"""Prints the current map to stdout."""
|
||||
|
||||
for i in range(len(self.map)):
|
||||
for j in range(len(self.map[0])):
|
||||
if self.pos == (i, j):
|
||||
print(self.direction, end="")
|
||||
else:
|
||||
print(self.map[i][j], end="")
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
m = Map()
|
||||
#m.load_map("testinput")
|
||||
m.load_map("input")
|
||||
|
||||
while m.step():
|
||||
print(m.pos, m.direction)
|
||||
#m.show()
|
||||
print(len(m.trace), m.trace)
|
||||
print(len(set(m.trace)))
|
||||
|
||||
10
2024/06/testinput
Normal file
10
2024/06/testinput
Normal file
@ -0,0 +1,10 @@
|
||||
....#.....
|
||||
.........#
|
||||
..........
|
||||
..#.......
|
||||
.......#..
|
||||
..........
|
||||
.#..^.....
|
||||
........#.
|
||||
#.........
|
||||
......#...
|
||||
Reference in New Issue
Block a user