day 6
This commit is contained in:
parent
a5ecc18f10
commit
1225a007ad
|
@ -0,0 +1,58 @@
|
||||||
|
import aocd
|
||||||
|
from enum import Enum, nonmember
|
||||||
|
|
||||||
|
class Direction(Enum):
|
||||||
|
NORTH = (0, -1)
|
||||||
|
WEST = (-1, 0)
|
||||||
|
SOUTH = (0, 1)
|
||||||
|
EAST = (1, 0)
|
||||||
|
|
||||||
|
@nonmember
|
||||||
|
def clockwise_from(d):
|
||||||
|
return list(Direction)[list(Direction).index(d) - 1]
|
||||||
|
|
||||||
|
def facing(coords, direction):
|
||||||
|
return tuple(map(sum, zip(coords, direction.value)))
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
"""
|
||||||
|
Given maze data, return
|
||||||
|
(Tuple of guard coords, set of obstacle coords, grid width, grid height)
|
||||||
|
"""
|
||||||
|
guard = None
|
||||||
|
obstacles = set()
|
||||||
|
|
||||||
|
for y, row in enumerate(data.split('\n')):
|
||||||
|
for x, char in enumerate(row):
|
||||||
|
if char == '#':
|
||||||
|
obstacles.add((x, y))
|
||||||
|
elif char == '^':
|
||||||
|
guard = (x, y)
|
||||||
|
|
||||||
|
return (guard, obstacles, x, y)
|
||||||
|
|
||||||
|
def solve(data):
|
||||||
|
guard, obstacles, width, height = parse(data)
|
||||||
|
guard_direction = Direction.NORTH
|
||||||
|
|
||||||
|
visited = set()
|
||||||
|
|
||||||
|
while (0 <= guard[0] <= width) and (0 <= guard[1] <= height):
|
||||||
|
visited.add(guard)
|
||||||
|
while (facing_tile := facing(guard, guard_direction)) in obstacles:
|
||||||
|
guard_direction = Direction.clockwise_from(guard_direction)
|
||||||
|
guard = facing_tile
|
||||||
|
|
||||||
|
return sum(1 for _ in visited)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
puz = aocd.models.Puzzle(year=2024, day=6)
|
||||||
|
|
||||||
|
# data = puz.examples[0].input_data
|
||||||
|
data = puz.input_data
|
||||||
|
|
||||||
|
solution = solve(data)
|
||||||
|
|
||||||
|
print(solution)
|
||||||
|
aocd.submit(solution, year=2024, day=6, part='a')
|
|
@ -0,0 +1,75 @@
|
||||||
|
import aocd
|
||||||
|
import collections
|
||||||
|
from enum import Enum, nonmember
|
||||||
|
|
||||||
|
class Direction(Enum):
|
||||||
|
NORTH = (0, -1)
|
||||||
|
WEST = (-1, 0)
|
||||||
|
SOUTH = (0, 1)
|
||||||
|
EAST = (1, 0)
|
||||||
|
|
||||||
|
@nonmember
|
||||||
|
def clockwise_from(d):
|
||||||
|
return list(Direction)[list(Direction).index(d) - 1]
|
||||||
|
|
||||||
|
def facing(coords, direction):
|
||||||
|
return tuple(map(sum, zip(coords, direction.value)))
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
"""
|
||||||
|
Given maze data, return
|
||||||
|
(Tuple of guard coords, set of obstacle coords, grid width, grid height)
|
||||||
|
"""
|
||||||
|
guard = None
|
||||||
|
obstacles = set()
|
||||||
|
|
||||||
|
for y, row in enumerate(data.split('\n')):
|
||||||
|
for x, char in enumerate(row):
|
||||||
|
if char == '#':
|
||||||
|
obstacles.add((x, y))
|
||||||
|
elif char == '^':
|
||||||
|
guard = (x, y)
|
||||||
|
|
||||||
|
return (guard, obstacles, x, y)
|
||||||
|
|
||||||
|
def simulate(guard, obstacles, width, height, return_visited_tiles=False):
|
||||||
|
guard_direction = Direction.NORTH
|
||||||
|
visited = collections.defaultdict(set)
|
||||||
|
|
||||||
|
while (0 <= guard[0] <= width) and (0 <= guard[1] <= height):
|
||||||
|
visited[guard].add(guard_direction)
|
||||||
|
while (facing_tile := facing(guard, guard_direction)) in obstacles:
|
||||||
|
guard_direction = Direction.clockwise_from(guard_direction)
|
||||||
|
|
||||||
|
# Loop detection, can only be true in modified grids
|
||||||
|
if guard_direction in visited[facing_tile]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
guard = facing_tile
|
||||||
|
|
||||||
|
# No loop found
|
||||||
|
|
||||||
|
if return_visited_tiles:
|
||||||
|
return set(k for k,v in visited.items() if v)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def solve(data):
|
||||||
|
guard, obstacles, width, height = parse(data)
|
||||||
|
|
||||||
|
# Only bother checking positions that the guard crosses
|
||||||
|
potential_positions = simulate(guard, obstacles, width, height, return_visited_tiles=True)
|
||||||
|
|
||||||
|
return sum(simulate(guard, obstacles | {p}, width, height) for p in potential_positions)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
puz = aocd.models.Puzzle(year=2024, day=6)
|
||||||
|
|
||||||
|
# data = puz.examples[0].input_data
|
||||||
|
data = puz.input_data
|
||||||
|
|
||||||
|
solution = solve(data)
|
||||||
|
|
||||||
|
print(solution)
|
||||||
|
aocd.submit(solution, year=2024, day=6, part='b')
|
Loading…
Reference in New Issue