diff --git a/2024/06/6.md b/2024/06/6.md new file mode 100644 index 0000000..d4805c4 --- /dev/null +++ b/2024/06/6.md @@ -0,0 +1,255 @@ +## \-\-- Day 6: Guard Gallivant \-\-- + +The Historians use their fancy [device](4) again, this time to whisk you +all away to the North Pole prototype suit manufacturing lab\... in the +year [1518](/2018/day/5)! It turns out that having direct access to +history is very convenient for a group of historians. + +You still have to be careful of time paradoxes, and so it will be +important to avoid anyone from 1518 while The Historians search for the +Chief. Unfortunately, a single *guard* is patrolling this part of the +lab. + +Maybe you can work out where the guard will go ahead of time so that The +Historians can search safely? + +You start by making a map (your puzzle input) of the situation. For +example: + + ....#..... + .........# + .......... + ..#....... + .......#.. + .......... + .#..^..... + ........#. + #......... + ......#... + +The map shows the current position of the guard with `^` (to indicate +the guard is currently facing *up* from the perspective of the map). Any +*obstructions* - crates, desks, alchemical reactors, etc. - are shown as +`#`. + +Lab guards in 1518 follow a very strict patrol protocol which involves +repeatedly following these steps: + +- If there is something directly in front of you, turn right 90 + degrees. +- Otherwise, take a step forward. + +Following the above protocol, the guard moves up several times until she +reaches an obstacle (in this case, a pile of failed suit prototypes): + + ....#..... + ....^....# + .......... + ..#....... + .......#.. + .......... + .#........ + ........#. + #......... + ......#... + +Because there is now an obstacle in front of the guard, she turns right +before continuing straight in her new facing direction: + + ....#..... + ........># + .......... + ..#....... + .......#.. + .......... + .#........ + ........#. + #......... + ......#... + +Reaching another obstacle (a spool of several *very* long polymers), she +turns right again and continues downward: + + ....#..... + .........# + .......... + ..#....... + .......#.. + .......... + .#......v. + ........#. + #......... + ......#... + +This process continues for a while, but the guard eventually leaves the +mapped area (after walking past a tank of universal solvent): + + ....#..... + .........# + .......... + ..#....... + .......#.. + .......... + .#........ + ........#. + #......... + ......#v.. + +By predicting the guard\'s route, you can determine which specific +positions in the lab will be in the patrol path. *Including the guard\'s +starting position*, the positions visited by the guard before leaving +the area are marked with an `X`: + + ....#..... + ....XXXXX# + ....X...X. + ..#.X...X. + ..XXXXX#X. + ..X.X.X.X. + .#XXXXXXX. + .XXXXXXX#. + #XXXXXXX.. + ......#X.. + +In this example, the guard will visit `41` distinct positions on your +map. + +Predict the path of the guard. *How many distinct positions will the +guard visit before leaving the mapped area?* + +Your puzzle answer was `5212`. + +## \-\-- Part Two \-\-- {#part2} + +While The Historians begin working around the guard\'s patrol route, you +borrow their fancy device and step outside the lab. From the safety of a +supply closet, you time travel through the last few months and +[record](/2018/day/4) the nightly status of the lab\'s guard post on the +walls of the closet. + +Returning after what seems like only a few seconds to The Historians, +they explain that the guard\'s patrol area is simply too large for them +to safely search the lab without getting caught. + +Fortunately, they are *pretty sure* that adding a single new obstruction +*won\'t* cause a time paradox. They\'d like to place the new obstruction +in such a way that the guard will get [*stuck in a +loop*]{title="This vulnerability was later fixed by having the guard always turn left instead."}, +making the rest of the lab safe to search. + +To have the lowest chance of creating a time paradox, The Historians +would like to know *all* of the possible positions for such an +obstruction. The new obstruction can\'t be placed at the guard\'s +starting position - the guard is there right now and would notice. + +In the above example, there are only `6` different positions where a new +obstruction would cause the guard to get stuck in a loop. The diagrams +of these six situations use `O` to mark the new obstruction, `|` to show +a position where the guard moves up/down, `-` to show a position where +the guard moves left/right, and `+` to show a position where the guard +moves both up/down and left/right. + +Option one, put a printing press next to the guard\'s starting position: + + ....#..... + ....+---+# + ....|...|. + ..#.|...|. + ....|..#|. + ....|...|. + .#.O^---+. + ........#. + #......... + ......#... + +Option two, put a stack of failed suit prototypes in the bottom right +quadrant of the mapped area: + + ....#..... + ....+---+# + ....|...|. + ..#.|...|. + ..+-+-+#|. + ..|.|.|.|. + .#+-^-+-+. + ......O.#. + #......... + ......#... + +Option three, put a crate of chimney-squeeze prototype fabric next to +the standing desk in the bottom right quadrant: + + ....#..... + ....+---+# + ....|...|. + ..#.|...|. + ..+-+-+#|. + ..|.|.|.|. + .#+-^-+-+. + .+----+O#. + #+----+... + ......#... + +Option four, put an alchemical retroencabulator near the bottom left +corner: + + ....#..... + ....+---+# + ....|...|. + ..#.|...|. + ..+-+-+#|. + ..|.|.|.|. + .#+-^-+-+. + ..|...|.#. + #O+---+... + ......#... + +Option five, put the alchemical retroencabulator a bit to the right +instead: + + ....#..... + ....+---+# + ....|...|. + ..#.|...|. + ..+-+-+#|. + ..|.|.|.|. + .#+-^-+-+. + ....|.|.#. + #..O+-+... + ......#... + +Option six, put a tank of sovereign glue right next to the tank of +universal solvent: + + ....#..... + ....+---+# + ....|...|. + ..#.|...|. + ..+-+-+#|. + ..|.|.|.|. + .#+-^-+-+. + .+----++#. + #+----++.. + ......#O.. + +It doesn\'t really matter what you choose to use as an obstacle so long +as you and The Historians can put it into position without the guard +noticing. The important thing is having enough options that you can find +one that minimizes time paradoxes, and in this example, there are `6` +different positions you could choose. + +You need to get the guard stuck in a loop by adding a single new +obstruction. *How many different positions could you choose for this +obstruction?* + +Your puzzle answer was `1767`. + +Both parts of this puzzle are complete! They provide two gold stars: +\*\* + +At this point, you should [return to your Advent calendar](/2024) and +try another puzzle. + +If you still want to see it, you can [get your puzzle +input](6/input). + diff --git a/2024/06/solution.py b/2024/06/solution.py new file mode 100644 index 0000000..c49ef8d --- /dev/null +++ b/2024/06/solution.py @@ -0,0 +1,125 @@ +#!/bin/python3 +import sys,re +from pprint import pprint +sys.path.insert(0, '../../') +from fred import list2int,get_re,nprint,lprint,loadFile,toGrid,get_value_in_direction,grid_valid + +input_f = 'input' + +part = 2 + +######################################### +# # +# Part 1 # +# # +######################################### + +if part == 1: + offsets = { + 'up': (-1, 0), + 'down': (1, 0), + 'left': (0, -1), + 'right': (0, 1), + } + + next_direction = { + 'up': 'right', + 'right': 'down', + 'down': 'left', + 'left': 'up' + } + grid = toGrid(input_f) + + center = () + steps = [] + for r in range(len(grid)): + for c in range(len(grid[0])): + if grid[r][c] == '^': + center = (r,c) + + pos = center + direction = 'up' + while grid_valid(pos[0],pos[1],grid): + + #dir = get_value_in_direction(grid, pos) + if get_value_in_direction(grid,pos,direction) != '#': + if pos not in steps: + steps.append(pos) + pos = (pos[0]+offsets[direction][0],pos[1]+offsets[direction][1]) + elif get_value_in_direction(grid,pos,direction) == '#': + direction = next_direction[direction] + + print(len(steps)) + + + +######################################### +# # +# Part 2 # +# # +######################################### +if part == 2: + offsets = { + 'up': (-1, 0), + 'down': (1, 0), + 'left': (0, -1), + 'right': (0, 1), + } + + next_direction = { + 'up': 'right', + 'right': 'down', + 'down': 'left', + 'left': 'up' + } + + direction = 'up' + + def isLoop(grid,pos,direction): + positions = [] + + while grid_valid(pos[0],pos[1],grid): + #nprint(grid,pos,'X') + if get_value_in_direction(grid,pos,direction) != '#': + cur = (pos[0],pos[1],direction) + + if cur not in positions: + positions.append(cur) + else: + return 1 + pos = (pos[0]+offsets[direction][0],pos[1]+offsets[direction][1]) + elif get_value_in_direction(grid,pos,direction) == '#': + direction = next_direction[direction] + #input() + return 0 + + grid = toGrid(input_f) + + + start = () + steps = [] + for r in range(len(grid)): + for c in range(len(grid[0])): + if grid[r][c] == '^': + start = (r,c) + + pos = start + while grid_valid(pos[0],pos[1],grid): + + dir = get_value_in_direction(grid, pos) + if get_value_in_direction(grid,pos,direction) != '#': + if pos not in steps: + steps.append(pos) + pos = (pos[0]+offsets[direction][0],pos[1]+offsets[direction][1]) + elif get_value_in_direction(grid,pos,direction) == '#': + direction = next_direction[direction] + steps.remove(start) + print(len(steps)) + result = 0 + for idx,i in enumerate(steps): + print(idx) + new_grid = grid[:] + new_grid[i[0]][i[1]] = '#' + result += isLoop(new_grid,start,'up') + new_grid[i[0]][i[1]] = '.' + print(result) \ No newline at end of file