Solution to problem 16 in Python
This commit is contained in:
parent
54e6df8a52
commit
87287d9f2e
360
src/Year_2022/Day16.py
Normal file
360
src/Year_2022/Day16.py
Normal file
@ -0,0 +1,360 @@
|
||||
# --- Day 16: Proboscidea Volcanium ---
|
||||
|
||||
# The sensors have led you to the origin of the distress signal: yet another
|
||||
# handheld device, just like the one the Elves gave you. However, you don't see
|
||||
# any Elves around; instead, the device is surrounded by elephants! They must
|
||||
# have gotten lost in these tunnels, and one of the elephants apparently figured
|
||||
# out how to turn on the distress signal.
|
||||
|
||||
# The ground rumbles again, much stronger this time. What kind of cave is this,
|
||||
# exactly? You scan the cave with your handheld device; it reports mostly
|
||||
# igneous rock, some ash, pockets of pressurized gas, magma... this isn't just a
|
||||
# cave, it's a volcano!
|
||||
|
||||
# You need to get the elephants out of here, quickly. Your device estimates that
|
||||
# you have 30 minutes before the volcano erupts, so you don't have time to go
|
||||
# back out the way you came in.
|
||||
|
||||
# You scan the cave for other options and discover a network of pipes and
|
||||
# pressure-release valves. You aren't sure how such a system got into a volcano,
|
||||
# but you don't have time to complain; your device produces a report (your
|
||||
# puzzle input) of each valve's flow rate if it were opened (in pressure per
|
||||
# minute) and the tunnels you could use to move between the valves.
|
||||
|
||||
# There's even a valve in the room you and the elephants are currently standing
|
||||
# in labeled AA. You estimate it will take you one minute to open a single valve
|
||||
# and one minute to follow any tunnel from one valve to another. What is the
|
||||
# most pressure you could release?
|
||||
|
||||
# For example, suppose you had the following scan output:
|
||||
|
||||
# Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||
# Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||
# Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||
# Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||
# Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||
# Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||
# Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||
# Valve HH has flow rate=22; tunnel leads to valve GG
|
||||
# Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||
# Valve JJ has flow rate=21; tunnel leads to valve II
|
||||
|
||||
# All of the valves begin closed. You start at valve AA, but it must be damaged
|
||||
# or jammed or something: its flow rate is 0, so there's no point in opening it.
|
||||
# However, you could spend one minute moving to valve BB and another minute
|
||||
# opening it; doing so would release pressure during the remaining 28 minutes at
|
||||
# a flow rate of 13, a total eventual pressure release of 28 * 13 = 364. Then,
|
||||
# you could spend your third minute moving to valve CC and your fourth minute
|
||||
# opening it, providing an additional 26 minutes of eventual pressure release at
|
||||
# a flow rate of 2, or 52 total pressure released by valve CC.
|
||||
|
||||
# Making your way through the tunnels like this, you could probably open many or
|
||||
# all of the valves by the time 30 minutes have elapsed. However, you need to
|
||||
# release as much pressure as possible, so you'll need to be methodical.
|
||||
# Instead, consider this approach:
|
||||
|
||||
# == Minute 1 ==
|
||||
# No valves are open.
|
||||
# You move to valve DD.
|
||||
|
||||
# == Minute 2 ==
|
||||
# No valves are open.
|
||||
# You open valve DD.
|
||||
|
||||
# == Minute 3 ==
|
||||
# Valve DD is open, releasing 20 pressure.
|
||||
# You move to valve CC.
|
||||
|
||||
# == Minute 4 ==
|
||||
# Valve DD is open, releasing 20 pressure.
|
||||
# You move to valve BB.
|
||||
|
||||
# == Minute 5 ==
|
||||
# Valve DD is open, releasing 20 pressure.
|
||||
# You open valve BB.
|
||||
|
||||
# == Minute 6 ==
|
||||
# Valves BB and DD are open, releasing 33 pressure.
|
||||
# You move to valve AA.
|
||||
|
||||
# == Minute 7 ==
|
||||
# Valves BB and DD are open, releasing 33 pressure.
|
||||
# You move to valve II.
|
||||
|
||||
# == Minute 8 ==
|
||||
# Valves BB and DD are open, releasing 33 pressure.
|
||||
# You move to valve JJ.
|
||||
|
||||
# == Minute 9 ==
|
||||
# Valves BB and DD are open, releasing 33 pressure.
|
||||
# You open valve JJ.
|
||||
|
||||
# == Minute 10 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve II.
|
||||
|
||||
# == Minute 11 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve AA.
|
||||
|
||||
# == Minute 12 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve DD.
|
||||
|
||||
# == Minute 13 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve EE.
|
||||
|
||||
# == Minute 14 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve FF.
|
||||
|
||||
# == Minute 15 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve GG.
|
||||
|
||||
# == Minute 16 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You move to valve HH.
|
||||
|
||||
# == Minute 17 ==
|
||||
# Valves BB, DD, and JJ are open, releasing 54 pressure.
|
||||
# You open valve HH.
|
||||
|
||||
# == Minute 18 ==
|
||||
# Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
|
||||
# You move to valve GG.
|
||||
|
||||
# == Minute 19 ==
|
||||
# Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
|
||||
# You move to valve FF.
|
||||
|
||||
# == Minute 20 ==
|
||||
# Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
|
||||
# You move to valve EE.
|
||||
|
||||
# == Minute 21 ==
|
||||
# Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
|
||||
# You open valve EE.
|
||||
|
||||
# == Minute 22 ==
|
||||
# Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure.
|
||||
# You move to valve DD.
|
||||
|
||||
# == Minute 23 ==
|
||||
# Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure.
|
||||
# You move to valve CC.
|
||||
|
||||
# == Minute 24 ==
|
||||
# Valves BB, DD, EE, HH, and JJ are open, releasing 79 pressure.
|
||||
# You open valve CC.
|
||||
|
||||
# == Minute 25 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# == Minute 26 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# == Minute 27 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# == Minute 28 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# == Minute 29 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# == Minute 30 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# This approach lets you release the most pressure possible in 30 minutes with
|
||||
# this valve layout, 1651.
|
||||
|
||||
# Work out the steps to release the most pressure in 30 minutes. What is the
|
||||
# most pressure you can release?
|
||||
|
||||
|
||||
import re
|
||||
from collections import deque
|
||||
|
||||
with open("files/P16.txt") as f:
|
||||
data = f.read().splitlines()
|
||||
rates = {}
|
||||
tunnels = {}
|
||||
for line in data:
|
||||
parts = line.split()
|
||||
valve = parts[1]
|
||||
rate = int(re.search("\d+", line).group())
|
||||
if rate:
|
||||
rates[valve] = rate
|
||||
tunnel_list = re.search(r"valves? (.+)$", line).group(1)
|
||||
tunnels[valve] = tunnel_list.split(", ")
|
||||
|
||||
|
||||
def bfs(tunnels, start, targets):
|
||||
dist = {start: 0}
|
||||
seen = {start}
|
||||
queue = deque([start])
|
||||
while queue and any(target not in dist for target in targets):
|
||||
path = queue.popleft()
|
||||
for route in tunnels[path]:
|
||||
if route not in seen:
|
||||
seen.add(route)
|
||||
dist[route] = dist[path] + 1
|
||||
queue.append(route)
|
||||
return dist
|
||||
|
||||
|
||||
def find_paths(dist, rates, time):
|
||||
pressures = []
|
||||
paths = []
|
||||
stack = [(time, 0, ["AA"])]
|
||||
while stack:
|
||||
time, p, path = stack.pop()
|
||||
cur = path[-1]
|
||||
new = []
|
||||
for n, d in dist[cur].items():
|
||||
if d > time - 2 or n in path:
|
||||
continue
|
||||
tt = time - d - 1
|
||||
pp = p + rates[n] * tt
|
||||
s = tt, pp, path + [n]
|
||||
new.append(s)
|
||||
if new:
|
||||
stack.extend(new)
|
||||
else:
|
||||
pressures.append(p)
|
||||
# paths always start at AA, so no need to keep first location
|
||||
paths.append(path[1:])
|
||||
return pressures, paths
|
||||
|
||||
|
||||
def get_distances():
|
||||
dist = {}
|
||||
for start in ("AA", *rates):
|
||||
dist[start] = {}
|
||||
d = bfs(tunnels, start, rates)
|
||||
for rate in rates:
|
||||
if rate != start and rate in d:
|
||||
dist[start][rate] = d[rate]
|
||||
|
||||
return dist
|
||||
|
||||
|
||||
def part_1():
|
||||
dist = get_distances()
|
||||
p, _ = find_paths(dist, rates, 30)
|
||||
print(f"One can release up to {max(p)} pressure")
|
||||
|
||||
|
||||
# --- Part Two ---
|
||||
|
||||
# You're worried that even with an optimal approach, the pressure released won't
|
||||
# be enough. What if you got one of the elephants to help you?
|
||||
|
||||
# It would take you 4 minutes to teach an elephant how to open the right valves
|
||||
# in the right order, leaving you with only 26 minutes to actually execute your
|
||||
# plan. Would having two of you working together be better, even if it means
|
||||
# having less time? (Assume that you teach the elephant before opening any
|
||||
# valves yourself, giving you both the same full 26 minutes.)
|
||||
|
||||
# In the example above, you could teach the elephant to help you as follows:
|
||||
|
||||
# == Minute 1 ==
|
||||
# No valves are open.
|
||||
# You move to valve II.
|
||||
# The elephant moves to valve DD.
|
||||
|
||||
# == Minute 2 ==
|
||||
# No valves are open.
|
||||
# You move to valve JJ.
|
||||
# The elephant opens valve DD.
|
||||
|
||||
# == Minute 3 ==
|
||||
# Valve DD is open, releasing 20 pressure.
|
||||
# You open valve JJ.
|
||||
# The elephant moves to valve EE.
|
||||
|
||||
# == Minute 4 ==
|
||||
# Valves DD and JJ are open, releasing 41 pressure.
|
||||
# You move to valve II.
|
||||
# The elephant moves to valve FF.
|
||||
|
||||
# == Minute 5 ==
|
||||
# Valves DD and JJ are open, releasing 41 pressure.
|
||||
# You move to valve AA.
|
||||
# The elephant moves to valve GG.
|
||||
|
||||
# == Minute 6 ==
|
||||
# Valves DD and JJ are open, releasing 41 pressure.
|
||||
# You move to valve BB.
|
||||
# The elephant moves to valve HH.
|
||||
|
||||
# == Minute 7 ==
|
||||
# Valves DD and JJ are open, releasing 41 pressure.
|
||||
# You open valve BB.
|
||||
# The elephant opens valve HH.
|
||||
|
||||
# == Minute 8 ==
|
||||
# Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
|
||||
# You move to valve CC.
|
||||
# The elephant moves to valve GG.
|
||||
|
||||
# == Minute 9 ==
|
||||
# Valves BB, DD, HH, and JJ are open, releasing 76 pressure.
|
||||
# You open valve CC.
|
||||
# The elephant moves to valve FF.
|
||||
|
||||
# == Minute 10 ==
|
||||
# Valves BB, CC, DD, HH, and JJ are open, releasing 78 pressure.
|
||||
# The elephant moves to valve EE.
|
||||
|
||||
# == Minute 11 ==
|
||||
# Valves BB, CC, DD, HH, and JJ are open, releasing 78 pressure.
|
||||
# The elephant opens valve EE.
|
||||
|
||||
# (At this point, all valves are open.)
|
||||
|
||||
# == Minute 12 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# ...
|
||||
|
||||
# == Minute 20 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# ...
|
||||
|
||||
# == Minute 26 ==
|
||||
# Valves BB, CC, DD, EE, HH, and JJ are open, releasing 81 pressure.
|
||||
|
||||
# With the elephant helping, after 26 minutes, the best you could do would
|
||||
# release a total of 1707 pressure.
|
||||
|
||||
# With you and an elephant working together for 26 minutes, what is the most
|
||||
# pressure you could release?
|
||||
|
||||
|
||||
def part_2():
|
||||
dist = get_distances()
|
||||
# # Part Two
|
||||
all_paths = list(zip(*find_paths(dist, rates, 26)))
|
||||
# p, _ = find_paths(dist, rates, 26)
|
||||
p, paths = zip(*sorted(all_paths, reverse=True))
|
||||
i, j = 0, 1
|
||||
while any(path in paths[j] for path in paths[i]):
|
||||
j += 1
|
||||
combined_p = p[i] + p[j] # lower bound
|
||||
j_max = j # since p[i] can only decrease, j cannot exceed this
|
||||
for i in range(1, j_max):
|
||||
for j in range(i + 1, j_max + 1):
|
||||
if any(path in paths[j] for path in paths[i]):
|
||||
continue
|
||||
combined_p = max(combined_p, p[i] + p[j])
|
||||
# print(ans)
|
||||
print(f"An elephant and me could release up to {combined_p} pressure")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
part_1()
|
||||
part_2()
|
Loading…
Reference in New Issue
Block a user