day16; p2 takes ~18min; have fun! :)
This commit is contained in:
parent
4a12de2729
commit
e4e916d7bb
152
day16.py
Normal file
152
day16.py
Normal file
@ -0,0 +1,152 @@
|
||||
from collections import deque
|
||||
from itertools import product
|
||||
from tools.aoc import AOCDay
|
||||
from typing import Any
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
class Valve:
|
||||
def __init__(self, name: str, flowrate: int) -> None:
|
||||
self.name = name
|
||||
self.flowrate = flowrate
|
||||
self.tunnels = []
|
||||
|
||||
|
||||
def get_openable_valve_tunnels(valve: Valve, open_valves: set, time_remaining: int) -> set:
|
||||
tunnels = set()
|
||||
queue = deque()
|
||||
visited = set()
|
||||
queue.append((0, valve))
|
||||
while queue:
|
||||
d, v = queue.popleft()
|
||||
if v.name in visited:
|
||||
continue
|
||||
visited.add(v.name)
|
||||
if v.name not in open_valves and v.flowrate > 0 and d + 2 <= time_remaining:
|
||||
tunnels.add((d, v))
|
||||
for x in v.tunnels:
|
||||
queue.append((d + 1, x))
|
||||
|
||||
return tunnels
|
||||
|
||||
|
||||
def get_max_flow(valve: Valve, open_valves: set, time_remaining: int = 30) -> int:
|
||||
max_flow = 0
|
||||
|
||||
ov = get_openable_valve_tunnels(valve, open_valves, time_remaining)
|
||||
if time_remaining <= 0 or not ov:
|
||||
return 0
|
||||
|
||||
for d, v in ov:
|
||||
this_open_valves = open_valves.copy()
|
||||
if d + 2 > time_remaining:
|
||||
continue
|
||||
this_open_valves.add(v.name)
|
||||
this_open_flow = v.flowrate * (time_remaining - d - 1)
|
||||
this_flow = get_max_flow(v, this_open_valves, time_remaining - d - 1)
|
||||
if this_flow + this_open_flow > max_flow:
|
||||
max_flow = this_flow + this_open_flow
|
||||
|
||||
return max_flow
|
||||
|
||||
|
||||
def get_max_flow_double(valve1: Valve, valve2: Valve, open_valves: set, DP: dict, time_remaining_1: int = 26, time_remaining_2: int = 26, depth: int = 0) -> int:
|
||||
dp_key = valve1.name + valve2.name + "%02d" % time_remaining_1 + "%02d" % time_remaining_2 + "".join(list(sorted(open_valves)))
|
||||
dp_key2 = valve2.name + valve1.name + "%02d" % time_remaining_1 + "%02d" % time_remaining_2 + "".join(list(sorted(open_valves)))
|
||||
if dp_key in DP:
|
||||
return DP[dp_key]
|
||||
|
||||
if time_remaining_1 <= 0 and time_remaining_2 <= 0:
|
||||
return 0
|
||||
|
||||
ov1 = get_openable_valve_tunnels(valve1, open_valves, time_remaining_1)
|
||||
ov2 = get_openable_valve_tunnels(valve2, open_valves, time_remaining_2)
|
||||
|
||||
if not ov1 and not ov2:
|
||||
return 0
|
||||
|
||||
if not ov1:
|
||||
ov1 = {(99, valve1)}
|
||||
|
||||
if not ov2:
|
||||
ov2 = {(99, valve2)}
|
||||
|
||||
permut = product(ov1, ov2)
|
||||
|
||||
if depth == 0:
|
||||
pbar = tqdm(total=210)
|
||||
|
||||
max_flow = 0
|
||||
for v1, v2 in permut:
|
||||
if v1[1].name == v2[1].name:
|
||||
continue
|
||||
if depth == 0:
|
||||
pbar.update(1)
|
||||
this_open_values = open_valves.copy()
|
||||
d1, tv1 = v1
|
||||
d2, tv2 = v2
|
||||
this_open_flow = 0
|
||||
if d1 + 2 <= time_remaining_1:
|
||||
this_open_values.add(tv1.name)
|
||||
this_open_flow += tv1.flowrate * (time_remaining_1 - d1 - 1)
|
||||
else:
|
||||
tv1 = valve1
|
||||
if d2 + 2 <= time_remaining_2:
|
||||
this_open_values.add(tv2.name)
|
||||
this_open_flow += tv2.flowrate * (time_remaining_2 - d2 - 1)
|
||||
else:
|
||||
tv2 = valve2
|
||||
|
||||
this_flow_rate = get_max_flow_double(tv1, tv2, this_open_values, DP, time_remaining_1 - d1 - 1, time_remaining_2 - d2 - 1, depth + 1)
|
||||
if this_flow_rate + this_open_flow > max_flow:
|
||||
max_flow = this_flow_rate + this_open_flow
|
||||
|
||||
if depth == 0:
|
||||
pbar.close()
|
||||
DP[dp_key] = max_flow
|
||||
DP[dp_key2] = max_flow
|
||||
return max_flow
|
||||
|
||||
|
||||
class Day(AOCDay):
|
||||
inputs = [
|
||||
[
|
||||
(1651, "input16_test"),
|
||||
(1850, "input16"),
|
||||
],
|
||||
[
|
||||
(1707, "input16_test"),
|
||||
(2306, "input16"),
|
||||
]
|
||||
]
|
||||
|
||||
def get_valve_graph(self) -> Valve:
|
||||
valves = {}
|
||||
for line in self.getInput():
|
||||
p = line.split(" ")
|
||||
valve_name = p[1]
|
||||
flowrate = int(p[4][5:-1])
|
||||
tunnels = "".join(p[9:]).split(",")
|
||||
valves[valve_name] = Valve(valve_name, flowrate)
|
||||
valves[valve_name].tunnels = tunnels
|
||||
|
||||
for valve in valves.values():
|
||||
valve.tunnels = [valves[x] for x in valve.tunnels]
|
||||
for valve in valves.values():
|
||||
for v in valve.tunnels:
|
||||
if valve not in v.tunnels:
|
||||
v.tunnels.append(valve)
|
||||
|
||||
return valves["AA"]
|
||||
|
||||
def part1(self) -> Any:
|
||||
return get_max_flow(self.get_valve_graph(), set())
|
||||
|
||||
def part2(self) -> Any:
|
||||
root = self.get_valve_graph()
|
||||
return get_max_flow_double(root, root, set(), {})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
day = Day(2022, 16)
|
||||
day.run(verbose=True)
|
||||
60
inputs/input16
Normal file
60
inputs/input16
Normal file
@ -0,0 +1,60 @@
|
||||
Valve DR has flow rate=22; tunnels lead to valves DC, YA
|
||||
Valve IO has flow rate=14; tunnels lead to valves GE, CK, HY, XB
|
||||
Valve XY has flow rate=0; tunnels lead to valves IP, AR
|
||||
Valve UQ has flow rate=0; tunnels lead to valves XU, PD
|
||||
Valve FO has flow rate=0; tunnels lead to valves DL, NC
|
||||
Valve PU has flow rate=0; tunnels lead to valves ZJ, AN
|
||||
Valve MK has flow rate=0; tunnels lead to valves ZS, SB
|
||||
Valve HN has flow rate=0; tunnels lead to valves AA, DV
|
||||
Valve XF has flow rate=0; tunnels lead to valves XB, AA
|
||||
Valve OD has flow rate=13; tunnels lead to valves ZS, AF, SY, QQ, AR
|
||||
Valve GE has flow rate=0; tunnels lead to valves KR, IO
|
||||
Valve UF has flow rate=18; tunnels lead to valves QQ, AN, YE, GY
|
||||
Valve WK has flow rate=19; tunnel leads to valve PQ
|
||||
Valve PQ has flow rate=0; tunnels lead to valves WK, CW
|
||||
Valve XU has flow rate=0; tunnels lead to valves DV, UQ
|
||||
Valve SH has flow rate=0; tunnels lead to valves IP, AA
|
||||
Valve SY has flow rate=0; tunnels lead to valves ZJ, OD
|
||||
Valve OU has flow rate=0; tunnels lead to valves CK, DL
|
||||
Valve IP has flow rate=8; tunnels lead to valves CY, ML, YI, XY, SH
|
||||
Valve XZ has flow rate=0; tunnels lead to valves AM, PD
|
||||
Valve ZU has flow rate=0; tunnels lead to valves CW, SB
|
||||
Valve DC has flow rate=0; tunnels lead to valves CF, DR
|
||||
Valve QY has flow rate=0; tunnels lead to valves CW, MQ
|
||||
Valve XB has flow rate=0; tunnels lead to valves IO, XF
|
||||
Valve AF has flow rate=0; tunnels lead to valves PD, OD
|
||||
Valve GY has flow rate=0; tunnels lead to valves UF, ZC
|
||||
Valve ZC has flow rate=0; tunnels lead to valves GY, CW
|
||||
Valve ZJ has flow rate=25; tunnels lead to valves SY, PU
|
||||
Valve NC has flow rate=6; tunnels lead to valves HY, ML, NJ, AT, FO
|
||||
Valve DS has flow rate=0; tunnels lead to valves AT, DV
|
||||
Valve DV has flow rate=7; tunnels lead to valves FD, KR, HN, DS, XU
|
||||
Valve HY has flow rate=0; tunnels lead to valves NC, IO
|
||||
Valve WF has flow rate=0; tunnels lead to valves NJ, AA
|
||||
Valve CK has flow rate=0; tunnels lead to valves IO, OU
|
||||
Valve YE has flow rate=0; tunnels lead to valves CY, UF
|
||||
Valve LA has flow rate=0; tunnels lead to valves DL, ZM
|
||||
Valve QQ has flow rate=0; tunnels lead to valves OD, UF
|
||||
Valve AM has flow rate=0; tunnels lead to valves XZ, SB
|
||||
Valve AN has flow rate=0; tunnels lead to valves UF, PU
|
||||
Valve CL has flow rate=16; tunnels lead to valves YA, LD
|
||||
Valve CF has flow rate=12; tunnel leads to valve DC
|
||||
Valve FD has flow rate=0; tunnels lead to valves DV, DL
|
||||
Valve QU has flow rate=0; tunnels lead to valves LD, PD
|
||||
Valve AT has flow rate=0; tunnels lead to valves DS, NC
|
||||
Valve SB has flow rate=24; tunnels lead to valves MK, AM, ZU
|
||||
Valve YI has flow rate=0; tunnels lead to valves DL, IP
|
||||
Valve ZM has flow rate=0; tunnels lead to valves AA, LA
|
||||
Valve LD has flow rate=0; tunnels lead to valves CL, QU
|
||||
Valve AR has flow rate=0; tunnels lead to valves OD, XY
|
||||
Valve DL has flow rate=5; tunnels lead to valves FO, LA, YI, OU, FD
|
||||
Valve MQ has flow rate=0; tunnels lead to valves QY, PD
|
||||
Valve PD has flow rate=9; tunnels lead to valves MQ, QU, XZ, AF, UQ
|
||||
Valve KR has flow rate=0; tunnels lead to valves GE, DV
|
||||
Valve CY has flow rate=0; tunnels lead to valves YE, IP
|
||||
Valve AA has flow rate=0; tunnels lead to valves SH, XF, ZM, HN, WF
|
||||
Valve NJ has flow rate=0; tunnels lead to valves NC, WF
|
||||
Valve YA has flow rate=0; tunnels lead to valves CL, DR
|
||||
Valve ML has flow rate=0; tunnels lead to valves NC, IP
|
||||
Valve CW has flow rate=15; tunnels lead to valves QY, PQ, ZC, ZU
|
||||
Valve ZS has flow rate=0; tunnels lead to valves MK, OD
|
||||
10
inputs/input16_test
Normal file
10
inputs/input16_test
Normal file
@ -0,0 +1,10 @@
|
||||
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
|
||||
Loading…
Reference in New Issue
Block a user