Solved 2024/15 P1
This commit is contained in:
parent
e5d1db9508
commit
960f4f4a06
478
2024/15/15.md
Normal file
478
2024/15/15.md
Normal file
@ -0,0 +1,478 @@
|
||||
## \-\-- Day 15: Warehouse Woes \-\--
|
||||
|
||||
You appear back inside your own mini submarine! Each Historian drives
|
||||
their mini submarine in a different direction; maybe the Chief has his
|
||||
own submarine down here somewhere as well?
|
||||
|
||||
You look up to see a vast school of [lanternfish](/2021/day/6) swimming
|
||||
past you. On closer inspection, they seem quite anxious, so you drive
|
||||
your mini submarine over to see if you can help.
|
||||
|
||||
Because lanternfish populations grow rapidly, they need a lot of food,
|
||||
and that food needs to be stored somewhere. That\'s why these
|
||||
lanternfish have built elaborate warehouse complexes operated by robots!
|
||||
|
||||
These lanternfish seem so anxious because they have lost control of the
|
||||
robot that operates one of their most important warehouses! It is
|
||||
currently running
|
||||
amok,
|
||||
pushing around boxes in the warehouse with no regard for lanternfish
|
||||
logistics *or* lanternfish inventory management strategies.
|
||||
|
||||
Right now, none of the lanternfish are brave enough to swim up to an
|
||||
unpredictable robot so they could shut it off. However, if you could
|
||||
anticipate the robot\'s movements, maybe they could find a safe option.
|
||||
|
||||
The lanternfish already have a map of the warehouse and a list of
|
||||
movements the robot will *attempt* to make (your puzzle input). The
|
||||
problem is that the movements will sometimes fail as boxes are shifted
|
||||
around, making the actual movements of the robot difficult to predict.
|
||||
|
||||
For example:
|
||||
|
||||
##########
|
||||
#..O..O.O#
|
||||
#......O.#
|
||||
#.OO..O.O#
|
||||
#..O@..O.#
|
||||
#O#..O...#
|
||||
#O..O..O.#
|
||||
#.OO.O.OO#
|
||||
#....O...#
|
||||
##########
|
||||
|
||||
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
|
||||
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
|
||||
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
|
||||
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
|
||||
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
|
||||
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
|
||||
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
|
||||
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
|
||||
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
|
||||
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
|
||||
|
||||
As the robot (`@`) attempts to move, if there are any boxes (`O`) in the
|
||||
way, the robot will also attempt to push those boxes. However, if this
|
||||
action would cause the robot or a box to move into a wall (`#`), nothing
|
||||
moves instead, including the robot. The initial positions of these are
|
||||
shown on the map at the top of the document the lanternfish gave you.
|
||||
|
||||
The rest of the document describes the *moves* (`^` for up, `v` for
|
||||
down, `<` for left, `>` for right) that the robot will attempt to make,
|
||||
in order. (The moves form a single giant sequence; they are broken into
|
||||
multiple lines just to make copy-pasting easier. Newlines within the
|
||||
move sequence should be ignored.)
|
||||
|
||||
Here is a smaller example to get started:
|
||||
|
||||
########
|
||||
#..O.O.#
|
||||
##@.O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
<^^>>>vv<v>>v<<
|
||||
|
||||
Were the robot to attempt the given sequence of moves, it would push
|
||||
around the boxes as follows:
|
||||
|
||||
Initial state:
|
||||
########
|
||||
#..O.O.#
|
||||
##@.O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move <:
|
||||
########
|
||||
#..O.O.#
|
||||
##@.O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move ^:
|
||||
########
|
||||
#.@O.O.#
|
||||
##..O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move ^:
|
||||
########
|
||||
#.@O.O.#
|
||||
##..O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move >:
|
||||
########
|
||||
#..@OO.#
|
||||
##..O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move >:
|
||||
########
|
||||
#...@OO#
|
||||
##..O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move >:
|
||||
########
|
||||
#...@OO#
|
||||
##..O..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#......#
|
||||
########
|
||||
|
||||
Move v:
|
||||
########
|
||||
#....OO#
|
||||
##..@..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move v:
|
||||
########
|
||||
#....OO#
|
||||
##..@..#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move <:
|
||||
########
|
||||
#....OO#
|
||||
##.@...#
|
||||
#...O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move v:
|
||||
########
|
||||
#....OO#
|
||||
##.....#
|
||||
#..@O..#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move >:
|
||||
########
|
||||
#....OO#
|
||||
##.....#
|
||||
#...@O.#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move >:
|
||||
########
|
||||
#....OO#
|
||||
##.....#
|
||||
#....@O#
|
||||
#.#.O..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move v:
|
||||
########
|
||||
#....OO#
|
||||
##.....#
|
||||
#.....O#
|
||||
#.#.O@.#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move <:
|
||||
########
|
||||
#....OO#
|
||||
##.....#
|
||||
#.....O#
|
||||
#.#O@..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
Move <:
|
||||
########
|
||||
#....OO#
|
||||
##.....#
|
||||
#.....O#
|
||||
#.#O@..#
|
||||
#...O..#
|
||||
#...O..#
|
||||
########
|
||||
|
||||
The larger example has many more moves; after the robot has finished
|
||||
those moves, the warehouse would look like this:
|
||||
|
||||
##########
|
||||
#.O.O.OOO#
|
||||
#........#
|
||||
#OO......#
|
||||
#OO@.....#
|
||||
#O#.....O#
|
||||
#O.....OO#
|
||||
#O.....OO#
|
||||
#OO....OO#
|
||||
##########
|
||||
|
||||
The lanternfish use their own custom Goods Positioning System (GPS for
|
||||
short) to track the locations of the boxes. The *GPS coordinate* of a
|
||||
box is equal to 100 times its distance from the top edge of the map plus
|
||||
its distance from the left edge of the map. (This process does not stop
|
||||
at wall tiles; measure all the way to the edges of the map.)
|
||||
|
||||
So, the box shown below has a distance of `1` from the top edge of the
|
||||
map and `4` from the left edge of the map, resulting in a GPS coordinate
|
||||
of `100 * 1 + 4 = 104`.
|
||||
|
||||
#######
|
||||
#...O..
|
||||
#......
|
||||
|
||||
The lanternfish would like to know the *sum of all boxes\' GPS
|
||||
coordinates* after the robot finishes moving. In the larger example, the
|
||||
sum of all boxes\' GPS coordinates is `10092`. In the smaller example,
|
||||
the sum is `2028`.
|
||||
|
||||
Predict the motion of the robot and boxes in the warehouse. After the
|
||||
robot is finished moving, *what is the sum of all boxes\' GPS
|
||||
coordinates?*
|
||||
|
||||
Your puzzle answer was `1568399`.
|
||||
|
||||
The first half of this puzzle is complete! It provides one gold star: \*
|
||||
|
||||
## \-\-- Part Two \-\-- {#part2}
|
||||
|
||||
The lanternfish use your information to find a safe moment to swim in
|
||||
and turn off the malfunctioning robot! Just as they start preparing a
|
||||
festival in your honor, reports start coming in that a *second*
|
||||
warehouse\'s robot is *also* malfunctioning.
|
||||
|
||||
This warehouse\'s layout is surprisingly similar to the one you just
|
||||
helped. There is one key difference: everything except the robot is
|
||||
*twice as wide*! The robot\'s list of movements doesn\'t change.
|
||||
|
||||
To get the wider warehouse\'s map, start with your original map and, for
|
||||
each tile, make the following changes:
|
||||
|
||||
- If the tile is `#`, the new map contains `##` instead.
|
||||
- If the tile is `O`, the new map contains `[]` instead.
|
||||
- If the tile is `.`, the new map contains `..` instead.
|
||||
- If the tile is `@`, the new map contains `@.` instead.
|
||||
|
||||
This will produce a new warehouse map which is twice as wide and with
|
||||
wide boxes that are represented by `[]`. (The robot does not change
|
||||
size.)
|
||||
|
||||
The larger example from before would now look like this:
|
||||
|
||||
####################
|
||||
##....[]....[]..[]##
|
||||
##............[]..##
|
||||
##..[][]....[]..[]##
|
||||
##....[]@.....[]..##
|
||||
##[]##....[]......##
|
||||
##[]....[]....[]..##
|
||||
##..[][]..[]..[][]##
|
||||
##........[]......##
|
||||
####################
|
||||
|
||||
Because boxes are now twice as wide but the robot is still the same size
|
||||
and speed, boxes can be aligned such that they directly push two other
|
||||
boxes at once. For example, consider this situation:
|
||||
|
||||
#######
|
||||
#...#.#
|
||||
#.....#
|
||||
#..OO@#
|
||||
#..O..#
|
||||
#.....#
|
||||
#######
|
||||
|
||||
<vv<<^^<<^^
|
||||
|
||||
After appropriately resizing this map, the robot would push around these
|
||||
boxes as follows:
|
||||
|
||||
Initial state:
|
||||
##############
|
||||
##......##..##
|
||||
##..........##
|
||||
##....[][]@.##
|
||||
##....[]....##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move <:
|
||||
##############
|
||||
##......##..##
|
||||
##..........##
|
||||
##...[][]@..##
|
||||
##....[]....##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move v:
|
||||
##############
|
||||
##......##..##
|
||||
##..........##
|
||||
##...[][]...##
|
||||
##....[].@..##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move v:
|
||||
##############
|
||||
##......##..##
|
||||
##..........##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##.......@..##
|
||||
##############
|
||||
|
||||
Move <:
|
||||
##############
|
||||
##......##..##
|
||||
##..........##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##......@...##
|
||||
##############
|
||||
|
||||
Move <:
|
||||
##############
|
||||
##......##..##
|
||||
##..........##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##.....@....##
|
||||
##############
|
||||
|
||||
Move ^:
|
||||
##############
|
||||
##......##..##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##.....@....##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move ^:
|
||||
##############
|
||||
##......##..##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##.....@....##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move <:
|
||||
##############
|
||||
##......##..##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##....@.....##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move <:
|
||||
##############
|
||||
##......##..##
|
||||
##...[][]...##
|
||||
##....[]....##
|
||||
##...@......##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move ^:
|
||||
##############
|
||||
##......##..##
|
||||
##...[][]...##
|
||||
##...@[]....##
|
||||
##..........##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
Move ^:
|
||||
##############
|
||||
##...[].##..##
|
||||
##...@.[]...##
|
||||
##....[]....##
|
||||
##..........##
|
||||
##..........##
|
||||
##############
|
||||
|
||||
This warehouse also uses GPS to locate the boxes. For these larger
|
||||
boxes, distances are measured from the edge of the map to the closest
|
||||
edge of the box in question. So, the box shown below has a distance of
|
||||
`1` from the top edge of the map and `5` from the left edge of the map,
|
||||
resulting in a GPS coordinate of `100 * 1 + 5 = 105`.
|
||||
|
||||
##########
|
||||
##...[]...
|
||||
##........
|
||||
|
||||
In the scaled-up version of the larger example from above, after the
|
||||
robot has finished all of its moves, the warehouse would look like this:
|
||||
|
||||
####################
|
||||
##[].......[].[][]##
|
||||
##[]...........[].##
|
||||
##[]........[][][]##
|
||||
##[]......[]....[]##
|
||||
##..##......[]....##
|
||||
##..[]............##
|
||||
##..@......[].[][]##
|
||||
##......[][]..[]..##
|
||||
####################
|
||||
|
||||
The sum of these boxes\' GPS coordinates is `9021`.
|
||||
|
||||
Predict the motion of the robot and boxes in this new, scaled-up
|
||||
warehouse. *What is the sum of all boxes\' final GPS coordinates?*
|
||||
|
||||
Answer:
|
||||
|
||||
Although it hasn\'t changed, you can still [get your puzzle
|
||||
input](15/input).
|
||||
|
355
2024/15/solution.py
Normal file
355
2024/15/solution.py
Normal file
@ -0,0 +1,355 @@
|
||||
#!/bin/python3
|
||||
import sys,time,re
|
||||
from pprint import pprint
|
||||
sys.path.insert(0, '../../')
|
||||
from fred import list2int,get_re,lprint, grid_valid,get_value_in_direction,addTuples,subTuples
|
||||
from termcolor import colored
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
input_f = 'test3'
|
||||
|
||||
def nprint(grid, cur: set = None, sign: str = None, positions:list = None):
|
||||
"""
|
||||
Prints a grid, highlighting the current position if specified.
|
||||
|
||||
Args:
|
||||
grid (list): A 2D grid to print.
|
||||
cur (set, optional): A set containing the (row, col) indices of the current position.
|
||||
Defaults to None.
|
||||
sign (str, optional): The sign to highlight the current position with. Defaults to None.
|
||||
positions (list, optional): A list of sets containing the (row, col) indices of positions to color.
|
||||
Defaults to None.
|
||||
Returns:
|
||||
None
|
||||
|
||||
Raises:
|
||||
TypeError: If cur is not a set or sign is not a string.
|
||||
"""
|
||||
if cur is not None and not isinstance(cur, tuple):
|
||||
raise TypeError("Cur must be a tuple with (row, column) indices.")
|
||||
if sign is not None and not isinstance(sign, str):
|
||||
raise TypeError("Sign must be a string.")
|
||||
if positions is not None and not isinstance(positions, list):
|
||||
raise TypeError("Positions must be a list.")
|
||||
|
||||
prepend = 0
|
||||
for idx, i in enumerate(grid):
|
||||
for jdx, j in enumerate(i):
|
||||
if jdx == 0:
|
||||
prepend = str(idx)+' '
|
||||
else:
|
||||
prepend = ''
|
||||
|
||||
if (idx, jdx) == cur:
|
||||
if sign is not None:
|
||||
if len(sign) > 1:
|
||||
print(prepend+sign[0] + grid[idx][jdx] + sign[1], end='') # Print with sign
|
||||
else:
|
||||
print(prepend+colored(sign,'green',attrs=["underline","bold"]), end=' ') # Print sign
|
||||
else:
|
||||
print(prepend+colored(grid[idx][jdx],'green',attrs=["underline","bold"]), end=' ')
|
||||
else:
|
||||
if positions is not None:
|
||||
if (idx,jdx) in positions:
|
||||
print(prepend+colored(grid[idx][jdx],'red'),end=' ')
|
||||
else:
|
||||
|
||||
print(prepend+grid[idx][jdx], end=' ')
|
||||
else:
|
||||
if grid[idx][jdx] == '.':
|
||||
print(prepend+colored(grid[idx][jdx],'blue',attrs=["concealed"]),end=' ')
|
||||
elif grid[idx][jdx] == 'O':
|
||||
print(prepend+colored(grid[idx][jdx],'red'),end=' ')
|
||||
elif grid[idx][jdx] == '#':
|
||||
print(prepend+colored(grid[idx][jdx],'white'),end=' ')
|
||||
else:
|
||||
print(prepend+grid[idx][jdx], end=' ') # Regular grid element
|
||||
print()
|
||||
|
||||
|
||||
for r in range(len(grid[0])):
|
||||
if r == 0:
|
||||
print(' ',end='')
|
||||
print(r,end=' ')
|
||||
print()
|
||||
|
||||
|
||||
def loadFile(input_f):
|
||||
grid = []
|
||||
instructions = []
|
||||
with open(input_f) as file:
|
||||
for line in file:
|
||||
# load map part
|
||||
if line.startswith("#"):
|
||||
grid.append(list(line.rstrip()))
|
||||
|
||||
# load instructions
|
||||
elif line.startswith(('v','<','>','^')):
|
||||
instructions += list(line.rstrip())
|
||||
return grid,instructions
|
||||
|
||||
#########################################
|
||||
# #
|
||||
# Part 1 #
|
||||
# #
|
||||
#########################################
|
||||
def part1():
|
||||
grid, instructions = loadFile(input_f)
|
||||
|
||||
start = ()
|
||||
|
||||
for r,row in enumerate(grid):
|
||||
for c, col in enumerate(row):
|
||||
if grid[r][c] == '@':
|
||||
start = (r,c)
|
||||
|
||||
# translate arrows to something get_value_in_direction can use
|
||||
directions = {
|
||||
'^':('up',(-1, 0)),
|
||||
'v':('down',(1, 0)),
|
||||
'>':('right',(0, 1)),
|
||||
'<':('left',(0, -1)),
|
||||
}
|
||||
|
||||
pos = start
|
||||
#print('Initial state')
|
||||
#nprint(grid,pos)
|
||||
#print()
|
||||
#input()
|
||||
for idx, inst in enumerate(instructions):
|
||||
#print('Move',inst,'(',len(instructions)-idx,')')
|
||||
dir = directions[inst][0]
|
||||
next = get_value_in_direction(grid,pos,dir)
|
||||
|
||||
# If wall, don't do anything
|
||||
if next == '#':
|
||||
#nprint(grid,pos)
|
||||
#input()
|
||||
continue
|
||||
|
||||
# If free space, move there
|
||||
if next == '.':
|
||||
grid[pos[0]][pos[1]] = '.'
|
||||
pos = addTuples(pos,directions[inst][1])
|
||||
grid[pos[0]][pos[1]] = '@'
|
||||
|
||||
# If box, move the box and the stack of boxes.
|
||||
if next == 'O':
|
||||
#print('@',pos)
|
||||
prev = pos
|
||||
next_chars = ['@']
|
||||
next_poss = [pos]
|
||||
skip = False
|
||||
while True:
|
||||
nextPos = addTuples(pos,directions[inst][1])
|
||||
nextChar = get_value_in_direction(grid,nextPos)
|
||||
#print(nextPos,nextChar)
|
||||
if nextChar == 'O':
|
||||
next_chars.append(nextChar)
|
||||
next_poss.append(nextPos)
|
||||
pos = nextPos
|
||||
if nextChar == '.':
|
||||
next_chars.append(nextChar)
|
||||
next_poss.append(nextPos)
|
||||
break
|
||||
if nextChar == '#':
|
||||
skip = True
|
||||
pos = prev
|
||||
break
|
||||
|
||||
#input()
|
||||
if not skip:
|
||||
for ndx,n in enumerate(next_poss):
|
||||
if ndx == 0:
|
||||
grid[n[0]][n[1]] = '.'
|
||||
pos = next_poss[ndx+1]
|
||||
else:
|
||||
grid[n[0]][n[1]] = next_chars[ndx-1]
|
||||
#input()
|
||||
#nprint(grid,pos)
|
||||
#print(len(instructions)-idx)
|
||||
#time.sleep(0.05)
|
||||
#input()
|
||||
result = 0
|
||||
for r,row in enumerate(grid):
|
||||
for c,char in enumerate(row):
|
||||
if char == 'O':
|
||||
result += (100*r+c)
|
||||
return result
|
||||
start_time = time.time()
|
||||
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
|
||||
|
||||
|
||||
#########################################
|
||||
# #
|
||||
# Part 2 #
|
||||
# #
|
||||
#########################################
|
||||
|
||||
def resizeGrid(grid:list) -> list:
|
||||
newGrid = []
|
||||
for r,row in enumerate(grid):
|
||||
newRow = []
|
||||
for c, char in enumerate(row):
|
||||
if char == '#':
|
||||
newRow.append('#')
|
||||
newRow.append('#')
|
||||
if char == 'O':
|
||||
newRow.append('[')
|
||||
newRow.append(']')
|
||||
if char == '.':
|
||||
newRow.append('.')
|
||||
newRow.append('.')
|
||||
if char == '@':
|
||||
newRow.append('@')
|
||||
newRow.append('.')
|
||||
newGrid.append(newRow)
|
||||
return newGrid
|
||||
|
||||
def part2():
|
||||
|
||||
|
||||
def nprint2(grid, cur: set = None, sign: str = None, positions:list = None):
|
||||
|
||||
|
||||
prepend = 0
|
||||
for idx, i in enumerate(grid):
|
||||
for jdx, j in enumerate(i):
|
||||
if jdx == 0:
|
||||
prepend = str(idx)+' '
|
||||
else:
|
||||
prepend = ''
|
||||
|
||||
if (idx, jdx) == cur:
|
||||
if sign is not None:
|
||||
if len(sign) > 1:
|
||||
print(prepend+sign[0] + grid[idx][jdx] + sign[1], end=' ') # Print with sign
|
||||
else:
|
||||
print(prepend+colored(sign,'green',attrs=["underline","bold"]), end=' ') # Print sign
|
||||
else:
|
||||
print(prepend+colored(grid[idx][jdx],'green',attrs=["underline","bold"]), end='')
|
||||
else:
|
||||
if positions is not None:
|
||||
if (idx,jdx) in positions:
|
||||
print(prepend+colored(grid[idx][jdx],'red'),end=' ')
|
||||
else:
|
||||
|
||||
print(prepend+grid[idx][jdx], end=' ')
|
||||
else:
|
||||
if grid[idx][jdx] == '.':
|
||||
print(prepend+colored(grid[idx][jdx],'blue',attrs=["concealed"]),end='')
|
||||
elif grid[idx][jdx] == 'O':
|
||||
print(prepend+colored(grid[idx][jdx],'red'),end='')
|
||||
elif grid[idx][jdx] == '#':
|
||||
print(prepend+colored(grid[idx][jdx],'white'),end='')
|
||||
else:
|
||||
print(prepend+grid[idx][jdx], end='') # Regular grid element
|
||||
print()
|
||||
|
||||
|
||||
for r in range(len(grid[0])):
|
||||
if r == 0:
|
||||
print(' 0',end='')
|
||||
|
||||
else:
|
||||
if r%2 == 0:
|
||||
print(r,end='')
|
||||
else:
|
||||
print(' ',end='')
|
||||
print()
|
||||
for r in range(len(grid[0])):
|
||||
if r == 0:
|
||||
print(' ',end='')
|
||||
|
||||
else:
|
||||
if r%2 != 0:
|
||||
print(r,end='')
|
||||
else:
|
||||
if r != 9:
|
||||
print(' ',end='')
|
||||
else:
|
||||
print('',end='')
|
||||
print()
|
||||
|
||||
|
||||
grid, instructions = loadFile(input_f)
|
||||
|
||||
start = ()
|
||||
|
||||
for r,row in enumerate(grid):
|
||||
for c, col in enumerate(row):
|
||||
if grid[r][c] == '@':
|
||||
start = (r,c)
|
||||
|
||||
# translate arrows to something get_value_in_direction can use
|
||||
directions = {
|
||||
'^':('up',(-1, 0)),
|
||||
'v':('down',(1, 0)),
|
||||
'>':('right',(0, 1)),
|
||||
'<':('left',(0, -1)),
|
||||
}
|
||||
|
||||
pos = start
|
||||
|
||||
nprint(grid)
|
||||
#print(grid)
|
||||
grid = resizeGrid(grid)
|
||||
print()
|
||||
nprint2(grid)
|
||||
#print(grid)
|
||||
|
||||
print()
|
||||
|
||||
for idx, inst in enumerate(instructions):
|
||||
#print('Move',inst,'(',len(instructions)-idx,')')
|
||||
dir = directions[inst][0]
|
||||
next = get_value_in_direction(grid,pos,dir)
|
||||
|
||||
# If wall, don't do anything
|
||||
if next == '#':
|
||||
#nprint(grid,pos)
|
||||
#input()
|
||||
continue
|
||||
|
||||
# If free space, move there
|
||||
if next == '.':
|
||||
grid[pos[0]][pos[1]] = '.'
|
||||
pos = addTuples(pos,directions[inst][1])
|
||||
grid[pos[0]][pos[1]] = '@'
|
||||
|
||||
# If box, move the box and the stack of boxes.
|
||||
if next == 'O':
|
||||
#print('@',pos)
|
||||
prev = pos
|
||||
next_chars = ['@']
|
||||
next_poss = [pos]
|
||||
skip = False
|
||||
while True:
|
||||
nextPos = addTuples(pos,directions[inst][1])
|
||||
nextChar = get_value_in_direction(grid,nextPos)
|
||||
#print(nextPos,nextChar)
|
||||
if nextChar == 'O':
|
||||
next_chars.append(nextChar)
|
||||
next_poss.append(nextPos)
|
||||
pos = nextPos
|
||||
if nextChar == '.':
|
||||
next_chars.append(nextChar)
|
||||
next_poss.append(nextPos)
|
||||
break
|
||||
if nextChar == '#':
|
||||
skip = True
|
||||
pos = prev
|
||||
break
|
||||
|
||||
#input()
|
||||
if not skip:
|
||||
for ndx,n in enumerate(next_poss):
|
||||
if ndx == 0:
|
||||
grid[n[0]][n[1]] = '.'
|
||||
pos = next_poss[ndx+1]
|
||||
else:
|
||||
grid[n[0]][n[1]] = next_chars[ndx-1]
|
||||
|
||||
start_time = time.time()
|
||||
print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms')
|
Binary file not shown.
28
fred.py
28
fred.py
@ -267,23 +267,39 @@ def nprint(grid, cur: set = None, sign: str = None, positions:list = None):
|
||||
if positions is not None and not isinstance(positions, list):
|
||||
raise TypeError("Positions must be a list.")
|
||||
|
||||
prepend = 0
|
||||
for idx, i in enumerate(grid):
|
||||
for jdx, j in enumerate(i):
|
||||
if jdx == 0:
|
||||
prepend = str(idx)+' '
|
||||
else:
|
||||
prepend = ''
|
||||
|
||||
if (idx, jdx) == cur:
|
||||
if len(sign) > 1:
|
||||
print(sign[0] + grid[idx][jdx] + sign[1], end='') # Print with sign
|
||||
if sign is not None:
|
||||
if len(sign) > 1:
|
||||
print(prepend+sign[0] + grid[idx][jdx] + sign[1], end='') # Print with sign
|
||||
else:
|
||||
print(prepend+colored(sign,'green',attrs=["underline"]), end=' ') # Print sign
|
||||
else:
|
||||
print(colored(sign,'blue'), end=' ') # Print sign
|
||||
print(prepend+colored(grid[idx][jdx],'green',attrs=["underline"]), end=' ')
|
||||
else:
|
||||
if positions is not None:
|
||||
if (idx,jdx) in positions:
|
||||
print(colored(grid[idx][jdx],'red'),end=' ')
|
||||
print(prepend+colored(grid[idx][jdx],'red'),end=' ')
|
||||
else:
|
||||
print(grid[idx][jdx], end=' ')
|
||||
print(prepend+grid[idx][jdx], end=' ')
|
||||
else:
|
||||
print(grid[idx][jdx], end=' ') # Regular grid element
|
||||
print(prepend+grid[idx][jdx], end=' ') # Regular grid element
|
||||
print()
|
||||
|
||||
|
||||
for r in range(len(grid[0])):
|
||||
if r == 0:
|
||||
print(' ',end='')
|
||||
print(r,end=' ')
|
||||
print()
|
||||
|
||||
def list2int(x):
|
||||
"""
|
||||
Converts a list of strings to a list of integers.
|
||||
|
Loading…
Reference in New Issue
Block a user