Move to proper folder
This commit is contained in:
140
src/Year_2022/Day12.py
Normal file
140
src/Year_2022/Day12.py
Normal file
@@ -0,0 +1,140 @@
|
||||
# --- Day 12: Hill Climbing Algorithm ---
|
||||
|
||||
# You try contacting the Elves using your handheld device, but the river you're
|
||||
# following must be too low to get a decent signal.
|
||||
|
||||
# You ask the device for a heightmap of the surrounding area (your puzzle
|
||||
# input). The heightmap shows the local area from above broken into a grid;
|
||||
# the elevation of each square of the grid is given by a single lowercase
|
||||
# letter, where a is the lowest elevation, b is the next-lowest, and so on up
|
||||
# to the highest elevation, z.
|
||||
|
||||
# Also included on the heightmap are marks for your current position (S) and
|
||||
# the location that should get the best signal (E). Your current position (S)
|
||||
# has elevation a, and the location that should get the best signal (E) has
|
||||
# elevation z.
|
||||
|
||||
# You'd like to reach E, but to save energy, you should do it in as few steps
|
||||
# as possible. During each step, you can move exactly one square up, down,
|
||||
# left, or right. To avoid needing to get out your climbing gear, the elevation
|
||||
# of the destination square can be at most one higher than the elevation of
|
||||
# your current square; that is, if your current elevation is m, you could step
|
||||
# to elevation n, but not to elevation o. (This also means that the elevation
|
||||
# of the destination square can be much lower than the elevation of your
|
||||
# current square.)
|
||||
|
||||
# For example:
|
||||
|
||||
# Sabqponm
|
||||
# abcryxxl
|
||||
# accszExk
|
||||
# acctuvwj
|
||||
# abdefghi
|
||||
|
||||
# Here, you start in the top-left corner; your goal is near the middle. You
|
||||
# could start by moving down or right, but eventually you'll need to head
|
||||
# toward the e at the bottom. From there, you can spiral around to the goal:
|
||||
|
||||
# v..v<<<<
|
||||
# >v.vv<<^
|
||||
# .>vv>E^^
|
||||
# ..v>>>^^
|
||||
# ..>>>>>^
|
||||
|
||||
# In the above diagram, the symbols indicate whether the path exits each
|
||||
# square moving up (^), down (v), left (<), or right (>). The location that
|
||||
# should get the best signal is still E, and . marks unvisited squares.
|
||||
|
||||
# This path reaches the goal in 31 steps, the fewest possible.
|
||||
|
||||
# What is the fewest steps required to move from your current position to the
|
||||
# location that should get the best signal?
|
||||
|
||||
with open("/home/xfeluser/AoC_2022/P12.txt") as f:
|
||||
diagram = {
|
||||
(x, y): ord(e)
|
||||
for y, line in enumerate(f.read().strip().split("\n"))
|
||||
for x, e in enumerate(line.strip())
|
||||
}
|
||||
|
||||
start = [k for k in diagram if diagram[k] == ord("S")][0]
|
||||
end = [k for k in diagram if diagram[k] == ord("E")][0]
|
||||
# Use expected value for starting/ending point
|
||||
diagram[start] = ord("a")
|
||||
diagram[end] = ord("z")
|
||||
|
||||
queue = [(start, 0)]
|
||||
pos_to_steps = {}
|
||||
|
||||
while queue:
|
||||
cur, steps = queue.pop()
|
||||
|
||||
if cur not in pos_to_steps or steps < pos_to_steps[cur]:
|
||||
pos_to_steps[cur] = steps
|
||||
|
||||
for offset in ((1, 0), (-1, 0), (0, 1), (0, -1)):
|
||||
new_pos = cur[0] + offset[0], cur[1] + offset[1]
|
||||
|
||||
if new_pos in diagram and diagram[new_pos] - diagram[cur] <= 1:
|
||||
queue.append((new_pos, steps + 1))
|
||||
|
||||
print(pos_to_steps[end])
|
||||
|
||||
|
||||
# --- Part Two ---
|
||||
|
||||
# As you walk up the hill, you suspect that the Elves will want to turn this
|
||||
# into a hiking trail. The beginning isn't very scenic, though; perhaps you can
|
||||
# find a better starting point.
|
||||
|
||||
# To maximize exercise while hiking, the trail should start as low as possible:
|
||||
# elevation a. The goal is still the square marked E. However, the trail should
|
||||
# still be direct, taking the fewest steps to reach its goal. So, you'll need
|
||||
# to find the shortest path from any square at elevation a to the square marked
|
||||
# E.
|
||||
|
||||
# Again consider the example from above:
|
||||
|
||||
# Sabqponm
|
||||
# abcryxxl
|
||||
# accszExk
|
||||
# acctuvwj
|
||||
# abdefghi
|
||||
|
||||
# Now, there are six choices for starting position (five marked a, plus the
|
||||
# square marked S that counts as being at elevation a). If you start at the
|
||||
# bottom-left square, you can reach the goal most quickly:
|
||||
|
||||
# ...v<<<<
|
||||
# ...vv<<^
|
||||
# ...v>E^^
|
||||
# .>v>>>^^
|
||||
# >^>>>>>^
|
||||
|
||||
# This path reaches the goal in only 29 steps, the fewest possible.
|
||||
|
||||
# What is the fewest steps required to move starting from any square with
|
||||
# elevation a to the location that should get the best signal?
|
||||
|
||||
starts = []
|
||||
pos_to_steps = {}
|
||||
|
||||
for start in [k for k in diagram if diagram[k] == ord("a")]:
|
||||
queue = [(start, 0)]
|
||||
|
||||
while queue:
|
||||
cur, steps = queue.pop()
|
||||
|
||||
if cur not in pos_to_steps or steps < pos_to_steps[cur]:
|
||||
pos_to_steps[cur] = steps
|
||||
|
||||
for offset in ((1, 0), (-1, 0), (0, 1), (0, -1)):
|
||||
new_pos = cur[0] + offset[0], cur[1] + offset[1]
|
||||
|
||||
if new_pos in diagram and diagram[new_pos] - diagram[cur] <= 1:
|
||||
queue.append((new_pos, steps + 1))
|
||||
|
||||
if end in pos_to_steps:
|
||||
starts.append(pos_to_steps[end])
|
||||
|
||||
print(min(starts))
|
||||
Reference in New Issue
Block a user