Day 06
# puzzle prompt: https://adventofcode.com/2024/day/6
import sys
import time
sys.path.insert(0, "..")
from base.advent import *
class Solution(InputAsLinesSolution):
_year = 2024
_day = 6
_is_debugging = False
def GetMaze(self, input):
maze = {}
for row, line in enumerate(input):
for col, cell in enumerate(line):
maze[(row, col)] = cell
if cell == "^":
curr = (row, col)
return maze, curr
# just walk the maze until out of bounds
def GetGuardRoute(self, input):
def Set():
maze[curr] = "."
maze[curr] = "^"
visited.add(curr)
maze, curr = self.GetMaze(input)
visited = set()
height = len(input)
width = len(input[0])
direction = "up"
visited.add(curr)
while True:
if direction == "up":
if curr[0] - 1 < 0: # out of bounds
break
elif maze[(curr[0] - 1, curr[1])] == "#":
direction = "right"
else:
curr = (curr[0] - 1, curr[1])
Set()
elif direction == "down":
if curr[0] + 1 >= height: # out of bounds
break
elif maze[(curr[0] + 1, curr[1])] == "#":
direction = "left"
else:
curr = (curr[0] + 1, curr[1])
Set()
elif direction == "right":
if curr[1] + 1 >= width: # out of bounds
break
elif maze[(curr[0], curr[1] + 1)] == "#":
direction = "down"
else:
curr = (curr[0], curr[1] + 1)
Set()
elif direction == "left":
if curr[1] - 1 < 0: # out of bounds
break
elif maze[(curr[0], curr[1] - 1)] == "#":
direction = "up"
else:
curr = (curr[0], curr[1] - 1)
Set()
return len(visited)
# took the simplest implementation, i make the guard walk and check if
# he already visited the cell
def TrapTheGuard(self, input):
def InLoop():
if (curr, direction) in visited:
return True
else:
visited.add((curr, direction))
return False
maze, start = self.GetMaze(input)
obstructions = 0
height = len(input)
width = len(input[0])
for cell in maze.keys():
if maze[cell] != ".":
continue
maze[cell] = "#" # obstruction
curr = start
direction = "up"
visited = set()
visited.add((curr, direction))
while True:
if direction == "up":
if curr[0] - 1 < 0:
break
elif maze[(curr[0] - 1, curr[1])] == "#":
direction = "right"
else:
maze[curr] = "."
curr = (curr[0] - 1, curr[1])
maze[curr] = "^"
if InLoop():
obstructions += 1
break
elif direction == "down":
if curr[0] + 1 >= height:
break
elif maze[(curr[0] + 1, curr[1])] == "#":
direction = "left"
else:
maze[curr] = "."
curr = (curr[0] + 1, curr[1])
maze[curr] = "^"
if InLoop():
obstructions += 1
break
elif direction == "right":
if curr[1] + 1 >= width:
break
elif maze[(curr[0], curr[1] + 1)] == "#":
direction = "down"
else:
maze[curr] = "."
curr = (curr[0], curr[1] + 1)
maze[curr] = "^"
if InLoop():
obstructions += 1
break
elif direction == "left":
if curr[1] - 1 < 0:
break
elif maze[(curr[0], curr[1] - 1)] == "#":
direction = "up"
else:
maze[curr] = "."
curr = (curr[0], curr[1] - 1)
maze[curr] = "^"
if InLoop():
obstructions += 1
break
# restore the original cells
maze[curr] = "."
maze[cell] = "."
return obstructions
def pt1(self, input):
self.debug(input)
res = self.GetGuardRoute(input)
return res
def pt2(self, input):
self.debug(input)
res = self.TrapTheGuard(input)
return res
def part_1(self):
start_time = time.time()
res = self.pt1(self.input)
end_time = time.time()
self.solve("1", res, (end_time - start_time))
def part_2(self):
start_time = time.time()
res = self.pt2(self.input)
end_time = time.time()
self.solve("2", res, (end_time - start_time))
if __name__ == "__main__":
solution = Solution()
solution.part_1()
solution.part_2()