Compare commits
10 Commits
a82057d89c
...
1d5bec6bde
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d5bec6bde | |||
| 55c0803250 | |||
| 1d61351d40 | |||
| 3853ccdbd7 | |||
| 1cf7be9ee2 | |||
| 6d4a35f85e | |||
|
|
7599c27d51 | ||
|
|
c4a78f9156 | ||
| 624e966ac6 | |||
| 6537628779 |
182
d16_old.py
Normal file
182
d16_old.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
from collections import deque
|
||||||
|
from itertools import product
|
||||||
|
from tools.aoc import AOCDay
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from tools.tools import Cache
|
||||||
|
|
||||||
|
|
||||||
|
class Valve:
|
||||||
|
def __init__(self, name: str, flowrate: int):
|
||||||
|
self.name: str = name
|
||||||
|
self.flowrate: int = flowrate
|
||||||
|
self.tunnels: set = set()
|
||||||
|
|
||||||
|
|
||||||
|
class Tunnel:
|
||||||
|
def __init__(self, target: Valve, length: int = 1):
|
||||||
|
self.target: Valve = target
|
||||||
|
self.length: int = length
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Tunnel(target={self.target.name}, length={self.length})"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
|
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 d + 1 <= time_remaining:
|
||||||
|
tunnels.add((d, v))
|
||||||
|
for x in v.tunnels:
|
||||||
|
queue.append((d + x.length, x.target))
|
||||||
|
|
||||||
|
return tunnels
|
||||||
|
|
||||||
|
|
||||||
|
def get_max_flow(valve: Valve, open_valves: list, time_remaining: int = 30, depth: int = 0) -> int:
|
||||||
|
max_flow = 0
|
||||||
|
|
||||||
|
ov = {t for t in valve.tunnels if t.target not in open_valves and t.length < time_remaining - 2}
|
||||||
|
if time_remaining <= 0 or not ov:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
for tunnel in ov:
|
||||||
|
this_open_flow = tunnel.target.flowrate * (time_remaining - tunnel.length - 1)
|
||||||
|
this_flow = get_max_flow(tunnel.target, open_valves + [tunnel.target], time_remaining - tunnel.length - 1, depth + 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: list, 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(open_valves)
|
||||||
|
dp_key2 = valve2.name + valve1.name + "%02d" % time_remaining_1 + "%02d" % time_remaining_2 + "".join(open_valves)
|
||||||
|
if dp_key in DP:
|
||||||
|
return DP[dp_key]
|
||||||
|
|
||||||
|
if time_remaining_1 <= 0 and time_remaining_2 <= 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
ov1 = {t for t in valve1.tunnels if t.target.name not in open_valves and t.length < time_remaining_1 - 2}
|
||||||
|
ov2 = {t for t in valve2.tunnels if t.target.name not in open_valves and t.length < time_remaining_2 - 2}
|
||||||
|
|
||||||
|
if not ov1 and not ov2:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if not ov1:
|
||||||
|
ov1 = {Tunnel(valve1, 99)}
|
||||||
|
|
||||||
|
if not ov2:
|
||||||
|
ov2 = {Tunnel(valve2, 99)}
|
||||||
|
|
||||||
|
permut = product(ov1, ov2)
|
||||||
|
|
||||||
|
max_flow = 0
|
||||||
|
for v1, v2 in permut:
|
||||||
|
if v1.target.name == v2.target.name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
this_open_flow = 0
|
||||||
|
|
||||||
|
t1 = valve1
|
||||||
|
if v1.length + 2 <= time_remaining_1:
|
||||||
|
this_open_flow += v1.target.flowrate * (time_remaining_1 - v1.length - 1)
|
||||||
|
t1 = v1.target
|
||||||
|
|
||||||
|
t2 = valve2
|
||||||
|
if v2.length + 2 <= time_remaining_2:
|
||||||
|
this_open_flow += v2.target.flowrate * (time_remaining_2 - v2.length - 1)
|
||||||
|
t2 = v2.target
|
||||||
|
|
||||||
|
this_flow_rate = get_max_flow_double(
|
||||||
|
t1,
|
||||||
|
t2,
|
||||||
|
sorted(open_valves + [v1.target.name, v2.target.name]),
|
||||||
|
DP,
|
||||||
|
time_remaining_1 - v1.length - 1,
|
||||||
|
time_remaining_2 - v2.length - 1,
|
||||||
|
depth + 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if this_flow_rate + this_open_flow > max_flow:
|
||||||
|
max_flow = this_flow_rate + this_open_flow
|
||||||
|
|
||||||
|
DP[dp_key] = max_flow
|
||||||
|
DP[dp_key2] = max_flow
|
||||||
|
return max_flow
|
||||||
|
|
||||||
|
|
||||||
|
class Day(AOCDay):
|
||||||
|
inputs = [
|
||||||
|
[
|
||||||
|
(1651, "input16_test"),
|
||||||
|
#(1947, "input16_dennis"),
|
||||||
|
(1850, "input16"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(1707, "input16_test"),
|
||||||
|
(2556, "input16_dennis"),
|
||||||
|
(2306, "input16"),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_valve_graph(self) -> Valve:
|
||||||
|
valves = {}
|
||||||
|
tmp_tunnels = {}
|
||||||
|
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)
|
||||||
|
tmp_tunnels[valve_name] = tunnels
|
||||||
|
|
||||||
|
for name, tunnels in tmp_tunnels.items():
|
||||||
|
valves[name].tunnels = {Tunnel(valves[t]) for t in tunnels}
|
||||||
|
|
||||||
|
for valve in valves.values():
|
||||||
|
tunnels = set()
|
||||||
|
queue = deque()
|
||||||
|
visited = set()
|
||||||
|
queue.append((0, valve))
|
||||||
|
while queue:
|
||||||
|
d, v = queue.popleft()
|
||||||
|
if v in visited:
|
||||||
|
continue
|
||||||
|
visited.add(v)
|
||||||
|
if v != valve and v.flowrate > 0:
|
||||||
|
tunnels.add(Tunnel(v, d))
|
||||||
|
for x in v.tunnels:
|
||||||
|
queue.append((d + 1, x.target))
|
||||||
|
|
||||||
|
tmp_tunnels[valve.name] = tunnels
|
||||||
|
|
||||||
|
for name, tunnels in tmp_tunnels.items():
|
||||||
|
valves[name].tunnels = tunnels
|
||||||
|
|
||||||
|
return valves["AA"]
|
||||||
|
|
||||||
|
def part1(self) -> Any:
|
||||||
|
return get_max_flow(self.get_valve_graph(), [])
|
||||||
|
|
||||||
|
def part2(self) -> Any:
|
||||||
|
cache = Cache()
|
||||||
|
root = self.get_valve_graph()
|
||||||
|
return get_max_flow_double(root, root, [], cache)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
day = Day(2022, 16)
|
||||||
|
day.run(verbose=True)
|
||||||
274
day16.py
274
day16.py
@ -1,124 +1,151 @@
|
|||||||
from collections import deque
|
import heapq
|
||||||
from itertools import product
|
import itertools
|
||||||
|
import re
|
||||||
from tools.aoc import AOCDay
|
from tools.aoc import AOCDay
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from tools.tools import Cache
|
|
||||||
|
|
||||||
|
|
||||||
class Valve:
|
class Valve:
|
||||||
def __init__(self, name: str, flowrate: int):
|
def __init__(self, name: str, flowrate: int) -> None:
|
||||||
self.name: str = name
|
self.__name = name
|
||||||
self.flowrate: int = flowrate
|
self.__flowrate = flowrate
|
||||||
self.tunnels: set = set()
|
self.neighbours = {}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def flowrate(self) -> int:
|
||||||
|
return self.__flowrate
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return self.__name
|
||||||
|
|
||||||
|
def shortest_path_to(self, other: 'Valve'):
|
||||||
|
if other in self.neighbours:
|
||||||
|
return self.neighbours[other]
|
||||||
|
|
||||||
|
current = self
|
||||||
|
v = set()
|
||||||
|
v.add(current)
|
||||||
|
q = [(v, k) for k, v in self.neighbours.items()]
|
||||||
|
heapq.heapify(q)
|
||||||
|
|
||||||
|
while q:
|
||||||
|
dist, current = heapq.heappop(q)
|
||||||
|
if current == other:
|
||||||
|
return dist
|
||||||
|
|
||||||
|
if current in v:
|
||||||
|
continue
|
||||||
|
|
||||||
|
v.add(current)
|
||||||
|
for n, d in current.neighbours.items():
|
||||||
|
heapq.heappush(q, (dist + d, n))
|
||||||
|
|
||||||
|
def __lt__(self, other: 'Valve') -> bool:
|
||||||
|
return self.__name < other.__name
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return "Valve(%s;%s)" % (self.__name, self.__flowrate)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.__repr__()
|
||||||
|
|
||||||
|
|
||||||
class Tunnel:
|
def get_most_pressure_release_solo(root: Valve, remaining_minutes: int = 30, visited: set = None) -> int:
|
||||||
def __init__(self, target: Valve, length: int = 1):
|
if visited is None:
|
||||||
self.target: Valve = target
|
visited = set()
|
||||||
self.length: int = length
|
visited.add(root)
|
||||||
|
|
||||||
def __str__(self):
|
my_flowrate = 0
|
||||||
return f"Tunnel(target={self.target.name}, length={self.length})"
|
if root.flowrate > 0:
|
||||||
|
remaining_minutes -= 1
|
||||||
|
my_flowrate = root.flowrate * remaining_minutes
|
||||||
|
|
||||||
def __repr__(self):
|
max_flowrate = 0
|
||||||
return str(self)
|
for n, d in root.neighbours.items():
|
||||||
|
if n in visited:
|
||||||
|
|
||||||
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
|
continue
|
||||||
visited.add(v.name)
|
|
||||||
if v.name not in open_valves and d + 2 <= time_remaining:
|
|
||||||
tunnels.add((d, v))
|
|
||||||
for x in v.tunnels:
|
|
||||||
queue.append((d + x.length, x.target))
|
|
||||||
|
|
||||||
return tunnels
|
if remaining_minutes <= d + 1:
|
||||||
|
continue
|
||||||
|
|
||||||
|
n_flowrate = get_most_pressure_release_solo(n, remaining_minutes - d, visited.copy())
|
||||||
|
if n_flowrate > max_flowrate:
|
||||||
|
max_flowrate = n_flowrate
|
||||||
|
|
||||||
|
return max_flowrate + my_flowrate
|
||||||
|
|
||||||
|
|
||||||
def get_max_flow(valve: Valve, open_valves: list, time_remaining: int = 30, depth: int = 0) -> int:
|
def get_mode_pressure_release_double(root_me: Valve, root_ele: Valve, r_min_me: int = 26, r_min_ele: int = 26, visited: set = None) -> int:
|
||||||
max_flow = 0
|
dp_key = root_me.name + root_ele.name + "%02d" % r_min_me + "%02d" % r_min_ele + "".join(v.name for v in sorted(visited))
|
||||||
|
dp_key2 = root_ele.name + root_me.name + "%02d" % r_min_me + "%02d" % r_min_ele + "".join(v.name for v in sorted(visited))
|
||||||
|
|
||||||
ov = {t for t in valve.tunnels if t.target not in open_valves and t.length < time_remaining - 2}
|
|
||||||
if time_remaining <= 0 or not ov:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
for tunnel in ov:
|
|
||||||
this_open_flow = tunnel.target.flowrate * (time_remaining - tunnel.length - 1)
|
|
||||||
this_flow = get_max_flow(tunnel.target, open_valves + [tunnel.target], time_remaining - tunnel.length - 1, depth + 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: list, 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(open_valves)
|
|
||||||
dp_key2 = valve2.name + valve1.name + "%02d" % time_remaining_1 + "%02d" % time_remaining_2 + "".join(open_valves)
|
|
||||||
if dp_key in DP:
|
if dp_key in DP:
|
||||||
return DP[dp_key]
|
return DP[dp_key]
|
||||||
|
|
||||||
if time_remaining_1 <= 0 and time_remaining_2 <= 0:
|
my_flowrate = 0
|
||||||
|
if r_min_me > 1 and root_me not in visited:
|
||||||
|
visited.add(root_me)
|
||||||
|
r_min_me -= 1
|
||||||
|
my_flowrate += root_me.flowrate * r_min_me
|
||||||
|
|
||||||
|
if r_min_ele > 1 and root_ele not in visited:
|
||||||
|
visited.add(root_ele)
|
||||||
|
r_min_ele -= 1
|
||||||
|
my_flowrate += root_ele.flowrate * r_min_ele
|
||||||
|
|
||||||
|
if not my_flowrate and root_me.name != 'AA':
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
ov1 = {t for t in valve1.tunnels if t.target.name not in open_valves and t.length < time_remaining_1 - 2}
|
max_flowrate = 0
|
||||||
ov2 = {t for t in valve2.tunnels if t.target.name not in open_valves and t.length < time_remaining_2 - 2}
|
rem_list = [x for x in root_me.neighbours.keys() if x not in visited]
|
||||||
|
if len(rem_list) == 1:
|
||||||
|
if root_me.neighbours[rem_list[0]] < root_ele.neighbours[rem_list[0]]:
|
||||||
|
max_flowrate = get_mode_pressure_release_double(rem_list[0], root_ele, r_min_me - root_me.neighbours[rem_list[0]], r_min_ele, visited.copy())
|
||||||
|
else:
|
||||||
|
max_flowrate = get_mode_pressure_release_double(root_me, rem_list[0], r_min_me, r_min_ele - root_ele.neighbours[rem_list[0]], visited.copy())
|
||||||
|
else:
|
||||||
|
max_prod = len(rem_list) ** 2
|
||||||
|
cur_prod = 0
|
||||||
|
for v1, v2 in itertools.product(rem_list, repeat=2):
|
||||||
|
if len(visited) == 1:
|
||||||
|
cur_prod += 1
|
||||||
|
print("Iter (%d/%d)" % (cur_prod, max_prod))
|
||||||
|
if v1 == v2:
|
||||||
|
continue
|
||||||
|
|
||||||
if not ov1 and not ov2:
|
me, ele = v1, v2
|
||||||
return 0
|
if r_min_me <= root_me.neighbours[me] + 1:
|
||||||
|
me = root_me
|
||||||
|
|
||||||
if not ov1:
|
if r_min_ele <= root_ele.neighbours[ele] + 1:
|
||||||
ov1 = {Tunnel(valve1, 99)}
|
ele = root_ele
|
||||||
|
|
||||||
if not ov2:
|
if me == root_me and ele == root_ele:
|
||||||
ov2 = {Tunnel(valve2, 99)}
|
continue
|
||||||
|
|
||||||
permut = product(ov1, ov2)
|
n_flowrate = get_mode_pressure_release_double(
|
||||||
|
me, ele,
|
||||||
|
r_min_me - (root_me.neighbours[me] if me in root_me.neighbours else 1),
|
||||||
|
r_min_ele - (root_ele.neighbours[ele] if ele in root_ele.neighbours else 1),
|
||||||
|
visited.copy()
|
||||||
|
)
|
||||||
|
if n_flowrate > max_flowrate:
|
||||||
|
max_flowrate = n_flowrate
|
||||||
|
|
||||||
max_flow = 0
|
if n_flowrate == 1671:
|
||||||
for v1, v2 in permut:
|
break
|
||||||
if v1.target.name == v2.target.name:
|
|
||||||
continue
|
|
||||||
|
|
||||||
this_open_flow = 0
|
DP[dp_key] = my_flowrate + max_flowrate
|
||||||
|
DP[dp_key2] = my_flowrate + max_flowrate
|
||||||
|
return my_flowrate + max_flowrate
|
||||||
|
|
||||||
t1 = valve1
|
|
||||||
if v1.length + 2 <= time_remaining_1:
|
|
||||||
this_open_flow += v1.target.flowrate * (time_remaining_1 - v1.length - 1)
|
|
||||||
t1 = v1.target
|
|
||||||
|
|
||||||
t2 = valve2
|
DP = {}
|
||||||
if v2.length + 2 <= time_remaining_2:
|
|
||||||
this_open_flow += v2.target.flowrate * (time_remaining_2 - v2.length - 1)
|
|
||||||
t2 = v2.target
|
|
||||||
|
|
||||||
this_flow_rate = get_max_flow_double(
|
|
||||||
t1,
|
|
||||||
t2,
|
|
||||||
sorted(open_valves + [v1.target.name, v2.target.name]),
|
|
||||||
DP,
|
|
||||||
time_remaining_1 - v1.length - 1,
|
|
||||||
time_remaining_2 - v2.length - 1,
|
|
||||||
depth + 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if this_flow_rate + this_open_flow > max_flow:
|
|
||||||
max_flow = this_flow_rate + this_open_flow
|
|
||||||
|
|
||||||
DP[dp_key] = max_flow
|
|
||||||
DP[dp_key2] = max_flow
|
|
||||||
return max_flow
|
|
||||||
|
|
||||||
|
|
||||||
class Day(AOCDay):
|
class Day(AOCDay):
|
||||||
|
input_regexp = re.compile(r'Valve ([A-Z][A-Z]) has flow rate=([0-9]+); tunnels? leads? to valves? (.*)')
|
||||||
inputs = [
|
inputs = [
|
||||||
[
|
[
|
||||||
(1651, "input16_test"),
|
(1651, "input16_test"),
|
||||||
@ -132,49 +159,54 @@ class Day(AOCDay):
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_valve_graph(self) -> Valve:
|
def parse_input(self) -> Valve:
|
||||||
|
n_cache = {}
|
||||||
valves = {}
|
valves = {}
|
||||||
tmp_tunnels = {}
|
|
||||||
for line in self.getInput():
|
for line in self.getInput():
|
||||||
p = line.split(" ")
|
name, flowrate, neighbours = self.input_regexp.match(line).groups()
|
||||||
valve_name = p[1]
|
valves[name] = Valve(name, int(flowrate))
|
||||||
flowrate = int(p[4][5:-1])
|
n_cache[name] = neighbours.split(", ")
|
||||||
tunnels = "".join(p[9:]).split(",")
|
|
||||||
valves[valve_name] = Valve(valve_name, flowrate)
|
|
||||||
tmp_tunnels[valve_name] = tunnels
|
|
||||||
|
|
||||||
for name, tunnels in tmp_tunnels.items():
|
for valve, neighbours in n_cache.items():
|
||||||
valves[name].tunnels = {Tunnel(valves[t]) for t in tunnels}
|
for n in neighbours:
|
||||||
|
valves[valve].neighbours[valves[n]] = 1
|
||||||
|
|
||||||
for valve in valves.values():
|
for valve in valves.values():
|
||||||
tunnels = set()
|
if valve.flowrate != 0:
|
||||||
queue = deque()
|
continue
|
||||||
visited = set()
|
|
||||||
queue.append((0, valve))
|
for n_set in valve.neighbours.keys():
|
||||||
while queue:
|
del n_set.neighbours[valve]
|
||||||
d, v = queue.popleft()
|
for n_get in valve.neighbours.keys():
|
||||||
if v in visited:
|
if n_get == n_set:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if n_get in n_set.neighbours:
|
||||||
|
continue
|
||||||
|
|
||||||
|
n_set.neighbours[n_get] = valve.neighbours[n_set] + valve.neighbours[n_get]
|
||||||
|
|
||||||
|
for v_set in valves.values():
|
||||||
|
for v_get in valves.values():
|
||||||
|
if v_set == v_get or v_get in v_set.neighbours or v_get.flowrate == 0:
|
||||||
continue
|
continue
|
||||||
visited.add(v)
|
|
||||||
if v != valve and v.flowrate > 0:
|
|
||||||
tunnels.add(Tunnel(v, d))
|
|
||||||
for x in v.tunnels:
|
|
||||||
queue.append((d + 1, x.target))
|
|
||||||
|
|
||||||
tmp_tunnels[valve.name] = tunnels
|
v_set.neighbours[v_get] = v_set.shortest_path_to(v_get)
|
||||||
|
|
||||||
for name, tunnels in tmp_tunnels.items():
|
for n in list(valves['AA'].neighbours.keys()):
|
||||||
valves[name].tunnels = tunnels
|
if n.flowrate == 0:
|
||||||
|
del valves['AA'].neighbours[n]
|
||||||
|
|
||||||
return valves["AA"]
|
return valves['AA']
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
return get_max_flow(self.get_valve_graph(), [])
|
return get_most_pressure_release_solo(self.parse_input())
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
cache = Cache()
|
global DP
|
||||||
root = self.get_valve_graph()
|
DP = {}
|
||||||
return get_max_flow_double(root, root, [], cache)
|
root_valve = self.parse_input()
|
||||||
|
return get_mode_pressure_release_double(root_valve, root_valve, visited={root_valve})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
387
day22.py
387
day22.py
@ -1,233 +1,42 @@
|
|||||||
import re
|
import re
|
||||||
from tools.aoc import AOCDay
|
from tools.aoc import AOCDay
|
||||||
from tools.coordinate import Coordinate
|
from tools.coordinate import Coordinate
|
||||||
from tools.grid import Grid
|
from tools.grid import Grid, GridTransformation
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
FACING = [
|
FACING = [
|
||||||
Coordinate(1, 0),
|
Coordinate(1, 0, 0),
|
||||||
Coordinate(0, 1),
|
Coordinate(0, 1, 0),
|
||||||
Coordinate(-1, 0),
|
Coordinate(-1, 0, 0),
|
||||||
Coordinate(0, -1)
|
Coordinate(0, -1, 0)
|
||||||
]
|
]
|
||||||
|
|
||||||
CUBE_CONNECTIONS = {
|
|
||||||
'##./.#./.##/..#': (
|
|
||||||
((0, 0, 1), (1, 1, 0)),
|
|
||||||
((0, 0, 2), (1, 2, 0)),
|
|
||||||
((0, 0, 3), (2, 3, 3)),
|
|
||||||
((1, 0, 0), (2, 2, 2)),
|
|
||||||
((1, 0, 3), (2, 3, 2)),
|
|
||||||
((1, 1, 0), (2, 2, 3)),
|
|
||||||
((1, 1, 2), (0, 0, 3)),
|
|
||||||
((1, 2, 2), (0, 0, 0)),
|
|
||||||
((1, 2, 3), (2, 3, 0)),
|
|
||||||
((2, 2, 0), (0, 1, 2)),
|
|
||||||
((2, 2, 3), (1, 1, 2)),
|
|
||||||
((2, 3, 0), (1, 0, 3)),
|
|
||||||
((2, 3, 1), (0, 0, 1)),
|
|
||||||
((2, 3, 2), (1, 2, 3)),
|
|
||||||
),
|
|
||||||
'..#./###./..##': (
|
|
||||||
((2, 0, 0), (3, 2, 2)),
|
|
||||||
((2, 0, 2), (1, 1, 1)),
|
|
||||||
((2, 0, 3), (0, 1, 1)),
|
|
||||||
((0, 1, 1), (2, 2, 3)),
|
|
||||||
((0, 1, 2), (3, 2, 3)),
|
|
||||||
((0, 1, 3), (2, 0, 1)),
|
|
||||||
((1, 1, 1), (2, 2, 0)),
|
|
||||||
((1, 1, 3), (2, 0, 0)),
|
|
||||||
((2, 1, 0), (3, 2, 1)),
|
|
||||||
((2, 2, 1), (0, 1, 3)),
|
|
||||||
((2, 2, 2), (1, 1, 3)),
|
|
||||||
((3, 2, 0), (2, 0, 2)),
|
|
||||||
((3, 2, 1), (0, 1, 0)),
|
|
||||||
((3, 2, 3), (2, 1, 2)),
|
|
||||||
),
|
|
||||||
'.#./.#./###/#..': (
|
|
||||||
((1, 0, 0), (2, 2, 2)),
|
|
||||||
((1, 0, 2), (0, 2, 0)),
|
|
||||||
((1, 0, 3), (0, 3, 0)),
|
|
||||||
((1, 1, 0), (2, 2, 3)),
|
|
||||||
((1, 1, 2), (0, 2, 1)),
|
|
||||||
((0, 2, 2), (1, 0, 0)),
|
|
||||||
((0, 2, 3), (1, 1, 0)),
|
|
||||||
((1, 2, 1), (0, 3, 2)),
|
|
||||||
((2, 2, 0), (1, 0, 2)),
|
|
||||||
((2, 2, 1), (0, 3, 3)),
|
|
||||||
((2, 2, 3), (1, 1, 2)),
|
|
||||||
((0, 3, 0), (1, 2, 3)),
|
|
||||||
((0, 3, 1), (2, 2, 1)),
|
|
||||||
((0, 3, 2), (1, 0, 1)),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_password_from_coord(c: Coordinate, face: int) -> int:
|
def get_password_from_coord(c: Coordinate, face: int) -> int:
|
||||||
return (c.y + 1) * 1000 + (c.x + 1) * 4 + face
|
return (c.y + 1) * 1000 + (c.x + 1) * 4 + face
|
||||||
|
|
||||||
|
|
||||||
def get_cube_conn_dict(cube_conn: tuple, c_size: int) -> dict:
|
def walk(board: Grid, pos: Coordinate, directions: list) -> (Coordinate, int):
|
||||||
conn_dict = {}
|
face = 0
|
||||||
for conn in cube_conn:
|
|
||||||
cur, tar = conn
|
|
||||||
cur_x, cur_y, cur_f = cur
|
|
||||||
tar_x, tar_y, tar_f = tar
|
|
||||||
|
|
||||||
match cur_f, tar_f:
|
|
||||||
case 0, 1:
|
|
||||||
x = (cur_x + 1) * c_size - 1
|
|
||||||
ty = tar_y * c_size
|
|
||||||
for d in range(c_size):
|
|
||||||
y = cur_y * c_size + d
|
|
||||||
tx = (tar_x + 1) * c_size - (d + 1)
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 0, 2:
|
|
||||||
x = (cur_x + 1) * c_size - 1
|
|
||||||
tx = (tar_x + 1) * c_size - 1
|
|
||||||
for dy in range(c_size):
|
|
||||||
y = cur_y * c_size + dy
|
|
||||||
ty = tar_y * c_size + dy
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 0, 3:
|
|
||||||
x = (cur_x + 1) * c_size - 1
|
|
||||||
ty = tar_y * c_size
|
|
||||||
for dy in range(c_size):
|
|
||||||
y = cur_y * c_size + dy
|
|
||||||
tx = tar_x * c_size + dy
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 1, 0:
|
|
||||||
y = (cur_y + 1) * c_size - 1
|
|
||||||
tx = tar_x * c_size
|
|
||||||
for dy in range(c_size):
|
|
||||||
x = cur_x * c_size + dy
|
|
||||||
ty = tar_y * c_size + dy
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 1, 1:
|
|
||||||
y = (cur_y + 1) * c_size - 1
|
|
||||||
ty = tar_y * c_size
|
|
||||||
for dx in range(c_size):
|
|
||||||
x = cur_x * c_size + dx
|
|
||||||
tx = tar_x * c_size + dx
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 1, 2:
|
|
||||||
y = (cur_y + 1) * c_size - 1
|
|
||||||
tx = (tar_x + 1) * c_size - 1
|
|
||||||
for d in range(c_size):
|
|
||||||
x = cur_x * c_size + d
|
|
||||||
ty = tar_y * c_size + d
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 1, 3:
|
|
||||||
y = (cur_y + 1) * c_size - 1
|
|
||||||
ty = (tar_y + 1) * c_size - 1
|
|
||||||
for d in range(c_size):
|
|
||||||
x = cur_x * c_size + d
|
|
||||||
tx = tar_x * c_size + d
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 2, 0:
|
|
||||||
x = cur_x * c_size
|
|
||||||
tx = tar_x * c_size
|
|
||||||
for dy in range(c_size):
|
|
||||||
y = cur_y * c_size + dy
|
|
||||||
ty = tar_y * c_size + dy
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 2, 1:
|
|
||||||
x = cur_x * c_size
|
|
||||||
ty = tar_y * c_size
|
|
||||||
for d in range(c_size):
|
|
||||||
y = cur_y * c_size + d
|
|
||||||
tx = tar_x * c_size + d
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 2, 3:
|
|
||||||
x = cur_x * c_size
|
|
||||||
ty = (tar_y + 1) * c_size - 1
|
|
||||||
for dy in range(c_size):
|
|
||||||
y = cur_y * c_size + dy
|
|
||||||
tx = tar_x * c_size + dy
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 3, 0:
|
|
||||||
y = cur_y * c_size
|
|
||||||
tx = tar_x * c_size
|
|
||||||
for d in range(c_size):
|
|
||||||
x = cur_x * c_size + d
|
|
||||||
ty = tar_y * c_size + d
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 3, 1:
|
|
||||||
y = cur_y * c_size
|
|
||||||
ty = (tar_y + 1) * c_size - 1
|
|
||||||
for d in range(c_size):
|
|
||||||
x = cur_x * c_size + d
|
|
||||||
tx = tar_x * c_size + d
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 3, 2:
|
|
||||||
y = cur_y * c_size
|
|
||||||
tx = (tar_x + 1) * c_size - 1
|
|
||||||
for d in range(c_size):
|
|
||||||
x = cur_x * c_size + d
|
|
||||||
ty = (tar_y + 1) * c_size - (d + 1)
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case 3, 3:
|
|
||||||
y = cur_y * c_size
|
|
||||||
ty = tar_y * c_size
|
|
||||||
for d in range(c_size):
|
|
||||||
x = cur_x * c_size + d
|
|
||||||
tx = tar_x * c_size + d
|
|
||||||
conn_dict[(x, y, cur_f)] = (Coordinate(tx, ty), tar_f)
|
|
||||||
case _:
|
|
||||||
print("Missing case:", cur_f, tar_f)
|
|
||||||
|
|
||||||
return conn_dict
|
|
||||||
|
|
||||||
|
|
||||||
def identify_cube(board: Grid) -> dict:
|
|
||||||
for i in ((4, 3), (3, 4), (2, 5), (5, 2)):
|
|
||||||
if (board.maxX + 1) % i[0] != 0 or (board.maxY + 1) % i[1] != 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
x_size, y_size = (board.maxX + 1) // i[0], (board.maxY + 1) // i[1]
|
|
||||||
if x_size != y_size:
|
|
||||||
continue # this cannot be a cube
|
|
||||||
x_tiles, y_tiles = (board.maxX + 1) // x_size, (board.maxY + 1) // y_size
|
|
||||||
cube_grid = Grid()
|
|
||||||
for x in range(x_tiles):
|
|
||||||
for y in range(y_tiles):
|
|
||||||
cube_grid.set(Coordinate(x, y), board.get(Coordinate(x * x_size, y * y_size)) is not None)
|
|
||||||
|
|
||||||
if cube_grid.getOnCount() != 6:
|
|
||||||
continue
|
|
||||||
|
|
||||||
cube_grid.print(true_char='#')
|
|
||||||
if str(cube_grid) in CUBE_CONNECTIONS:
|
|
||||||
return get_cube_conn_dict(CUBE_CONNECTIONS[str(cube_grid)], x_size)
|
|
||||||
|
|
||||||
print("Unknown Cube-Shape")
|
|
||||||
|
|
||||||
|
|
||||||
def walk(board: Grid, pos: Coordinate, directions: list, face: int = 0, connections: dict = None) -> (Coordinate, int):
|
|
||||||
for direction in directions:
|
for direction in directions:
|
||||||
steps, turn = direction
|
steps, turn = direction
|
||||||
print("starting at", pos, "moving", steps, "steps, then turning", turn)
|
|
||||||
|
|
||||||
for _ in range(steps):
|
for _ in range(steps):
|
||||||
next_pos = pos + FACING[face]
|
next_pos = pos + FACING[face]
|
||||||
next_face = face
|
next_face = face
|
||||||
if board.get(next_pos) is None or not board.isWithinBoundaries(next_pos):
|
if board.get(next_pos) is None or not board.isWithinBoundaries(next_pos):
|
||||||
if connections is not None:
|
match face:
|
||||||
next_pos, next_face = connections[(pos.x, pos.y, face)]
|
case 0:
|
||||||
print("wrapping from", pos, "to", next_pos, "facing", next_face)
|
next_pos = Coordinate(0, next_pos.y, 0)
|
||||||
else:
|
case 1:
|
||||||
match face:
|
next_pos = Coordinate(next_pos.x, 0, 0)
|
||||||
case 0:
|
case 2:
|
||||||
next_pos = Coordinate(0, next_pos.y)
|
next_pos = Coordinate(board.maxX, next_pos.y, 0)
|
||||||
case 1:
|
case 3:
|
||||||
next_pos = Coordinate(next_pos.x, 0)
|
next_pos = Coordinate(next_pos.x, board.maxY, 0)
|
||||||
case 2:
|
while board.get(next_pos) is None:
|
||||||
next_pos = Coordinate(board.maxX, next_pos.y)
|
next_pos += FACING[face]
|
||||||
case 3:
|
|
||||||
next_pos = Coordinate(next_pos.x, board.maxY)
|
|
||||||
while board.get(next_pos) is None:
|
|
||||||
next_pos += FACING[face]
|
|
||||||
|
|
||||||
next_val = board.get(next_pos)
|
next_val = board.get(next_pos)
|
||||||
if not next_val:
|
if not next_val:
|
||||||
@ -242,29 +51,121 @@ def walk(board: Grid, pos: Coordinate, directions: list, face: int = 0, connecti
|
|||||||
return pos, face
|
return pos, face
|
||||||
|
|
||||||
|
|
||||||
|
def cube_walk(board: Grid, pos: Coordinate, directions: list) -> (Coordinate, int):
|
||||||
|
face = 0
|
||||||
|
for direction in directions:
|
||||||
|
steps, turn = direction
|
||||||
|
|
||||||
|
for _ in range(steps):
|
||||||
|
next_pos = pos + FACING[face]
|
||||||
|
if board.get(next_pos) is False:
|
||||||
|
break
|
||||||
|
elif board.get(next_pos) is None:
|
||||||
|
match face:
|
||||||
|
case 0: # right
|
||||||
|
if board.get(Coordinate(pos.x + 1, pos.y, 1)) is True:
|
||||||
|
board.transform(GridTransformation.COUNTER_ROTATE_Y)
|
||||||
|
next_pos = Coordinate(1, pos.y, 0)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
case 1: # down
|
||||||
|
if board.get(Coordinate(pos.x, pos.y + 1, 1)) is True:
|
||||||
|
board.transform(GridTransformation.ROTATE_X)
|
||||||
|
next_pos = Coordinate(pos.x, 1, 0)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
case 2: # left
|
||||||
|
if board.get(Coordinate(0, pos.y, 1)) is True:
|
||||||
|
board.transform(GridTransformation.ROTATE_Y)
|
||||||
|
next_pos = Coordinate(board.maxX - 1, pos.y, 0)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
case 3: # up
|
||||||
|
if board.get(Coordinate(pos.x, 0, 1)) is True:
|
||||||
|
board.transform(GridTransformation.COUNTER_ROTATE_X)
|
||||||
|
next_pos = Coordinate(pos.x, board.maxY - 1, 0)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
pos = next_pos
|
||||||
|
|
||||||
|
if turn != 'S':
|
||||||
|
face = (face + (1 if turn == 'R' else -1)) % 4
|
||||||
|
|
||||||
|
return pos, face
|
||||||
|
|
||||||
|
|
||||||
|
def fold(board: Grid, start_pos: Coordinate):
|
||||||
|
c_size = 4 if board.maxX < 40 else 50 # account for test case
|
||||||
|
|
||||||
|
if board.get(start_pos + Coordinate(-1, 0, 0)) is not None:
|
||||||
|
for y in board.rangeY():
|
||||||
|
for x in range(start_pos.x - 1, board.minX - 1, -1):
|
||||||
|
from_c = Coordinate(x, y, 0)
|
||||||
|
to_c = Coordinate(start_pos.x - 1, y, start_pos.x - x)
|
||||||
|
board.set(to_c, board.get(from_c))
|
||||||
|
board.set(from_c, None)
|
||||||
|
board.recalcBoundaries()
|
||||||
|
board.transform(GridTransformation.ROTATE_Y)
|
||||||
|
board.shift(shift_z=-board.minZ)
|
||||||
|
fold(board, Coordinate(board.maxX - c_size, 1, 0))
|
||||||
|
board.transform(GridTransformation.COUNTER_ROTATE_Y)
|
||||||
|
board.shift_zero()
|
||||||
|
start_pos = Coordinate(1, 1, 0)
|
||||||
|
|
||||||
|
if board.get(start_pos + Coordinate(c_size, 0, 0)) is not None:
|
||||||
|
for y in range(board.maxY + 1):
|
||||||
|
for x in range(start_pos.x + c_size, board.maxX + 1):
|
||||||
|
from_c = Coordinate(x, y, 0)
|
||||||
|
to_c = Coordinate(start_pos.x + c_size, y, x - start_pos.x - c_size + 1)
|
||||||
|
board.set(to_c, board.get(from_c))
|
||||||
|
board.set(from_c, None)
|
||||||
|
board.recalcBoundaries()
|
||||||
|
board.transform(GridTransformation.COUNTER_ROTATE_Y)
|
||||||
|
board.shift(shift_z=-board.minZ)
|
||||||
|
fold(board, Coordinate(1, 1, 0))
|
||||||
|
board.transform(GridTransformation.ROTATE_Y)
|
||||||
|
board.shift_zero()
|
||||||
|
if board.get(Coordinate(start_pos.x, 0, 0)) is not None:
|
||||||
|
board.shift(shift_y=1)
|
||||||
|
if list(board.getActiveCells(x=0, z=0)):
|
||||||
|
board.shift(shift_x=1)
|
||||||
|
|
||||||
|
if board.get(start_pos + Coordinate(0, c_size, 0)) is not None:
|
||||||
|
for y in range(start_pos.y + c_size, board.maxY + 1):
|
||||||
|
for x in board.rangeX():
|
||||||
|
from_c = Coordinate(x, y, 0)
|
||||||
|
to_c = Coordinate(x, start_pos.y + c_size, y - start_pos.y - c_size + 1)
|
||||||
|
board.set(to_c, board.get(from_c))
|
||||||
|
board.set(from_c, None)
|
||||||
|
board.recalcBoundaries()
|
||||||
|
board.transform(GridTransformation.ROTATE_X)
|
||||||
|
fold(board, start_pos)
|
||||||
|
board.transform(GridTransformation.COUNTER_ROTATE_X)
|
||||||
|
|
||||||
|
|
||||||
class Day(AOCDay):
|
class Day(AOCDay):
|
||||||
inputs = [
|
inputs = [
|
||||||
[
|
[
|
||||||
(6032, "input22_test"),
|
(6032, "input22_test"),
|
||||||
|
(191010, "input22_dennis"),
|
||||||
(1428, "input22"),
|
(1428, "input22"),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
(5031, "input22_test"),
|
(5031, "input22_test"),
|
||||||
(None, "input22"),
|
(55364, "input22_dennis"),
|
||||||
|
(142380, "input22"),
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_map_and_directions(self) -> (Grid, list, Coordinate):
|
def get_map_and_directions(self) -> (Grid, list, Coordinate):
|
||||||
board_map = Grid(None)
|
|
||||||
start_pos = None
|
start_pos = None
|
||||||
map_lines, dir_line = self.getMultiLineInputAsArray()
|
map_lines, dir_line = self.getMultiLineInputAsArray()
|
||||||
for y, map_line in enumerate(map_lines):
|
board = Grid.from_str("/".join(map_lines), default=None, translate={' ': None, '#': False, '.': True}, mode3d=True)
|
||||||
for x, v in enumerate(map_line):
|
for x in board.rangeX():
|
||||||
if v in ['#', '.']:
|
if board.get(Coordinate(x, 0, 0)) is not None:
|
||||||
c = Coordinate(x, y)
|
start_pos = Coordinate(x, 0, 0)
|
||||||
if start_pos is None and v == '.':
|
break
|
||||||
start_pos = c
|
|
||||||
board_map.set(c, v == '.')
|
|
||||||
|
|
||||||
if dir_line[0][-1] not in ['R', 'L']:
|
if dir_line[0][-1] not in ['R', 'L']:
|
||||||
dir_line[0] += 'S'
|
dir_line[0] += 'S'
|
||||||
@ -272,29 +173,43 @@ class Day(AOCDay):
|
|||||||
for d in re.findall(r'\d+[RLS]', dir_line[0]):
|
for d in re.findall(r'\d+[RLS]', dir_line[0]):
|
||||||
directions.append((int(d[:-1]), d[-1]))
|
directions.append((int(d[:-1]), d[-1]))
|
||||||
|
|
||||||
return board_map, directions, start_pos
|
return board, directions, start_pos
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
board_map, directions, start_position = self.get_map_and_directions()
|
board, directions, start_position = self.get_map_and_directions()
|
||||||
finish, face = walk(board_map, start_position, directions)
|
finish, face = walk(board, start_position, directions)
|
||||||
return get_password_from_coord(finish, face)
|
return get_password_from_coord(finish, face)
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
board_map, directions, start_position = self.get_map_and_directions()
|
board, directions, start_position = self.get_map_and_directions()
|
||||||
conn = identify_cube(board_map)
|
board.shift(shift_x=1, shift_y=1)
|
||||||
for x in board_map.rangeX():
|
start_position += Coordinate(1, 1, 0)
|
||||||
c = Coordinate(x, 0)
|
fold(board, start_position)
|
||||||
if board_map.get(c) is not None:
|
finish, face = cube_walk(board, Coordinate(1, 1, 0), directions)
|
||||||
start_position = c
|
|
||||||
break
|
orig_board, _, _ = self.get_map_and_directions()
|
||||||
print(board_map.minX, board_map.minY, board_map.maxX, board_map.maxY)
|
c_size = 4 if orig_board.maxX < 50 else 50 # account for test case
|
||||||
print(start_position)
|
for x in range(0, orig_board.maxX + 1, c_size):
|
||||||
print(board_map.get(Coordinate(4, 0)))
|
for y in range(0, orig_board.maxY + 1, c_size):
|
||||||
print(conn)
|
check_pos = finish - Coordinate(1, 1, 0)
|
||||||
board_map.print(true_char='.')
|
check_face = face
|
||||||
finish, face = walk(board_map, start_position, directions, 0, conn)
|
sub_board = orig_board.sub_grid(x, y, x + c_size - 1, y + c_size - 1, 0, 0)
|
||||||
print(finish, face)
|
if len(sub_board.getActiveCells()) == 0:
|
||||||
print(get_password_from_coord(finish, face))
|
continue
|
||||||
|
check_board = board.sub_grid(1, 1, c_size, c_size, 0, 0)
|
||||||
|
for _ in range(2):
|
||||||
|
for _ in range(4):
|
||||||
|
check_board.transform(GridTransformation.ROTATE_Z)
|
||||||
|
check_pos = Coordinate(-check_pos.y + sub_board.maxY, check_pos.x, 0)
|
||||||
|
check_face = (check_face + 1) % 4
|
||||||
|
if sub_board == check_board:
|
||||||
|
check_pos += Coordinate(x, y, 0)
|
||||||
|
return get_password_from_coord(check_pos, check_face)
|
||||||
|
|
||||||
|
check_board.transform(GridTransformation.FLIP_X)
|
||||||
|
check_pos = Coordinate(abs(check_pos.x - c_size + 1), check_pos.y, 0)
|
||||||
|
check_face = (check_face + 2) % 4
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
6
day23.py
6
day23.py
@ -52,16 +52,18 @@ class Day(AOCDay):
|
|||||||
[
|
[
|
||||||
(25, "input23_test_small"),
|
(25, "input23_test_small"),
|
||||||
(110, "input23_test"),
|
(110, "input23_test"),
|
||||||
|
(4070, "input23_dennis"),
|
||||||
(3766, "input23"),
|
(3766, "input23"),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
(20, "input23_test"),
|
(20, "input23_test"),
|
||||||
|
(881, "input23_dennis"),
|
||||||
(954, "input23"),
|
(954, "input23"),
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
map = Grid.from_str("/".join(self.getInput()), true_char='#')
|
map = Grid.from_str("/".join(self.getInput()), translate={'#': True, '.': False})
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
if not move_elfs(map, i):
|
if not move_elfs(map, i):
|
||||||
@ -71,7 +73,7 @@ class Day(AOCDay):
|
|||||||
return (map.maxX - map.minX + 1) * (map.maxY - map.minY + 1) - map.getOnCount()
|
return (map.maxX - map.minX + 1) * (map.maxY - map.minY + 1) - map.getOnCount()
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
map = Grid.from_str("/".join(self.getInput()), true_char='#')
|
map = Grid.from_str("/".join(self.getInput()), translate={'#': True, '.': False})
|
||||||
round = 0
|
round = 0
|
||||||
|
|
||||||
while move_elfs(map, round):
|
while move_elfs(map, round):
|
||||||
|
|||||||
109
day24.py
Normal file
109
day24.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
from heapq import heappush, heappop
|
||||||
|
from tools.aoc import AOCDay
|
||||||
|
from tools.coordinate import Coordinate
|
||||||
|
from tools.grid import Grid
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def expand_valley(valley: Grid, to_z: int) -> None:
|
||||||
|
while valley.maxZ <= to_z:
|
||||||
|
for blizzard_pos in valley.getActiveCells(z=valley.maxZ):
|
||||||
|
for blizzard in valley.get(blizzard_pos):
|
||||||
|
next_pos = blizzard_pos + blizzard
|
||||||
|
if next_pos.x < 0:
|
||||||
|
next_pos = Coordinate(valley.maxX, next_pos.y, next_pos.z)
|
||||||
|
elif next_pos.x > valley.maxX:
|
||||||
|
next_pos = Coordinate(0, next_pos.y, next_pos.z)
|
||||||
|
elif next_pos.y < 0:
|
||||||
|
next_pos = Coordinate(next_pos.x, valley.maxY, next_pos.z)
|
||||||
|
elif next_pos.y > valley.maxY:
|
||||||
|
next_pos = Coordinate(next_pos.x, 0, next_pos.z)
|
||||||
|
|
||||||
|
if not valley.get(next_pos):
|
||||||
|
valley.set(next_pos, [blizzard])
|
||||||
|
else:
|
||||||
|
valley.get(next_pos).append(blizzard)
|
||||||
|
|
||||||
|
|
||||||
|
def get_min_steps(valley: Grid, pos: Coordinate, target: Coordinate) -> int:
|
||||||
|
check_list = [
|
||||||
|
Coordinate(1, 0, 1),
|
||||||
|
Coordinate(-1, 0, 1),
|
||||||
|
Coordinate(0, 0, 1),
|
||||||
|
Coordinate(0, 1, 1),
|
||||||
|
Coordinate(0, -1, 1)
|
||||||
|
]
|
||||||
|
q = []
|
||||||
|
heappush(q, (0, pos))
|
||||||
|
v = set()
|
||||||
|
while q:
|
||||||
|
_, cur_pos = heappop(q)
|
||||||
|
if cur_pos in v:
|
||||||
|
continue
|
||||||
|
v.add(cur_pos)
|
||||||
|
|
||||||
|
if cur_pos.z >= valley.maxZ:
|
||||||
|
expand_valley(valley, cur_pos.z + 1)
|
||||||
|
|
||||||
|
for c in check_list:
|
||||||
|
next_pos = cur_pos + c
|
||||||
|
if next_pos.x == target.x and next_pos.y == target.y:
|
||||||
|
return next_pos.z
|
||||||
|
if not valley.isWithinBoundaries(next_pos) and (next_pos.x != pos.x or next_pos.y != pos.y):
|
||||||
|
continue
|
||||||
|
if valley.get(next_pos):
|
||||||
|
continue
|
||||||
|
dist = abs(target.x - next_pos.x) + abs(target.y - next_pos.y)
|
||||||
|
heappush(q, (dist + next_pos.z, next_pos))
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
class Day(AOCDay):
|
||||||
|
inputs = [
|
||||||
|
[
|
||||||
|
(18, "input24_test"),
|
||||||
|
(297, "input24_dennis"),
|
||||||
|
(269, "input24"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(54, "input24_test"),
|
||||||
|
(856, "input24_dennis"),
|
||||||
|
(825, "input24"),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_valley(self) -> Grid:
|
||||||
|
valley = Grid.from_str(
|
||||||
|
"/".join(self.getInput()),
|
||||||
|
translate={
|
||||||
|
'#': False,
|
||||||
|
'.': False,
|
||||||
|
'>': [Coordinate(1, 0, 1)],
|
||||||
|
'<': [Coordinate(-1, 0, 1)],
|
||||||
|
'v': [Coordinate(0, 1, 1)],
|
||||||
|
'^': [Coordinate(0, -1, 1)],
|
||||||
|
},
|
||||||
|
default=False,
|
||||||
|
mode3d=True
|
||||||
|
)
|
||||||
|
valley.shift_zero()
|
||||||
|
|
||||||
|
return valley
|
||||||
|
|
||||||
|
def part1(self) -> Any:
|
||||||
|
valley = self.get_valley()
|
||||||
|
return get_min_steps(valley, Coordinate(0, -1, 0), Coordinate(valley.maxX, valley.maxY + 1))
|
||||||
|
|
||||||
|
def part2(self) -> Any:
|
||||||
|
valley = self.get_valley()
|
||||||
|
start = Coordinate(0, -1, 0)
|
||||||
|
target = Coordinate(valley.maxX, valley.maxY + 1)
|
||||||
|
steps = get_min_steps(valley, start, target)
|
||||||
|
steps = get_min_steps(valley, Coordinate(target.x, target.y, steps), start)
|
||||||
|
return get_min_steps(valley, Coordinate(start.x, start.y, steps), target)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
day = Day(2022, 24)
|
||||||
|
day.run(verbose=True)
|
||||||
58
day25.py
Normal file
58
day25.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
from tools.aoc import AOCDay
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def int2snafu(dec: int) -> str:
|
||||||
|
conv = "012=-0"
|
||||||
|
snafu = ""
|
||||||
|
power = 1
|
||||||
|
over = 0
|
||||||
|
while dec > 0:
|
||||||
|
c = dec % (5 ** power) + over
|
||||||
|
dec //= 5
|
||||||
|
if c > 2:
|
||||||
|
over = 1
|
||||||
|
else:
|
||||||
|
over = 0
|
||||||
|
|
||||||
|
snafu = conv[c] + snafu
|
||||||
|
|
||||||
|
return snafu
|
||||||
|
|
||||||
|
|
||||||
|
def snafu2int(snafu: str) -> int:
|
||||||
|
dec = 0
|
||||||
|
for i, c in enumerate(snafu):
|
||||||
|
if c == '-':
|
||||||
|
val = -1
|
||||||
|
elif c == '=':
|
||||||
|
val = -2
|
||||||
|
else:
|
||||||
|
val = int(c)
|
||||||
|
|
||||||
|
dec += 5 ** (len(snafu) - i - 1) * val
|
||||||
|
|
||||||
|
return dec
|
||||||
|
|
||||||
|
|
||||||
|
class Day(AOCDay):
|
||||||
|
inputs = [
|
||||||
|
[
|
||||||
|
("2=-1=0", "input25_test"),
|
||||||
|
("2==221=-002=0-02-000", "input25"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(None, "input25"),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
def part1(self) -> Any:
|
||||||
|
return int2snafu(sum(snafu2int(c) for c in self.getInput()))
|
||||||
|
|
||||||
|
def part2(self) -> Any:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
day = Day(2022, 25)
|
||||||
|
day.run(verbose=True)
|
||||||
202
inputs/input22_dennis
Normal file
202
inputs/input22_dennis
Normal file
File diff suppressed because one or more lines are too long
72
inputs/input23_dennis
Normal file
72
inputs/input23_dennis
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#.##......#...#.###......###.........####.##...#.###...####.#....#.#.#.#
|
||||||
|
..#.###..##.##.#.#.....#.###..###.#..........#..#...##..####.#.#..#..##.
|
||||||
|
#..#.###...##.....##.#.#####.#..##.....##...#.#.#....##.#..###.###....#.
|
||||||
|
#.###...###.#.##.#..#..#.##..##...##.#..##..#.##.##....#######...#..#...
|
||||||
|
....#.#.###...#.#..###.#.#..##....#####.#...##..#.#...##.##.....###..#.#
|
||||||
|
..###.#.#..#####..##.##....###......##.##..####.#.###....######.#.#.##..
|
||||||
|
#...###.##.##..###.####.####.#...###..##...#.#..#####.#...##...#..##..##
|
||||||
|
##.####....###.#####..#.#.###.##.#...#..##.##.###..#...##.#.#..###...#..
|
||||||
|
####...##..#..####...##.##..##.##..#.##.......#..#.##.#...###..######.##
|
||||||
|
.#.##.#.###.##.##........####.#...#.##...##..##.....#..##.#.###...######
|
||||||
|
#.......#...#####.#...#.###...####..####....##..###.##..##..######....#.
|
||||||
|
.##.###..#....#.#.#####.###..#.##......#...##..##...#..#.##.#...##..#..#
|
||||||
|
##.###......####.#..#####.....#..##.####.#.#....##...##.#.#.##...#.#.#..
|
||||||
|
.#.##..###.#.......#..##.##.#.#.........#.##.##.......##....##..#..#....
|
||||||
|
###..####.##..##..#....#..#..#.#.##..#........#...##.##.#.##...#.#...#.#
|
||||||
|
..#.#####.#..###.#.##..#..#...#.#...#...#..##.#.#..##..#.#...####..#...#
|
||||||
|
#...#####..#.####.#.##.##.#...##.#...#.....##.....#..#.###..#.#...#..#..
|
||||||
|
.##########...#..#..#......#.###.#......#..#.#..#..#.#..#..#.#.###.#...#
|
||||||
|
.##..#.##.###.#...##.#...#.##.#.##..##...#.#..#...#.....#.######..#.#.##
|
||||||
|
.#.#.....###......#.#.##.#..#...#....##.#..#.###...#.....###.##.####..##
|
||||||
|
..#..#.#...#.###..#..####....##.#........##..###..####....###..###.###..
|
||||||
|
#..##.###.#.#..#..#.##....#...#.#.###..#.#.....###..##..#####...##.#..#.
|
||||||
|
#.#......##.#.#.#.###.#.#...###..######.###.##.#.#....#####..#.#..###.##
|
||||||
|
........##.##.##..##.#.###.#..#.########.....#.#.##.##.#......########.#
|
||||||
|
#..#.#.#...#..#.#....###.....###.###.#.##....##...#...#..#.#..##.###.###
|
||||||
|
.#...####.#.#....#.####..#...##.#.##...#.#.####.#...#..##.###...#.###..#
|
||||||
|
......#...#..##.##.###.#..#.....######..##.####.#......#..##.......####.
|
||||||
|
...###.#..#.....#..#.####...#..#...#...##..#...##.##....####......###..#
|
||||||
|
#.###...#.##.######.#...#...##..#.#..##.#.#....#####.####.#.#......#..##
|
||||||
|
##.....#..####.#.#.###...#..#..#..#..#.#.#....###..##..#.#.#....#..#.##.
|
||||||
|
.#.#.....####.#.#...........#.#.##.####...#.#...#..#.#..####.#..#.#.##.#
|
||||||
|
...#..#...#.#.###..#.#..##...##.#.#..#.#####.#.##.###.#......#..##.#.###
|
||||||
|
...#....##########.######...#.....#..#.##...###..#.####.#.####..##..##..
|
||||||
|
#.##....#..#...####.......##.#..##.#.#..#######.....#.#.#.##..##..#.#...
|
||||||
|
###..##..#..#.#..###..#.#.#..###....##..#.#.....##..#..#....#....###.#.#
|
||||||
|
##.#.#..#.#######.......#..#.#.#...#..#.#..######..##..........##....#..
|
||||||
|
......##..#######.#..#...#.#####.#.#.#..#.####.####..##.##.#.##....#....
|
||||||
|
...#.###...######.#....#.#...###.##.#.#.###..#.#...####.#....#...#.#..#.
|
||||||
|
#.#...#.###..#####.###..##.#....#...#.##...#..#...####.#...#.##.#..#.#.#
|
||||||
|
##.#..##....##..#..######....##.##.....##..##....###....#####.#.##....##
|
||||||
|
#..#.#..#..###.##..#....#.##.#####.###.#.##.#..#.#..#####..###..###.#.##
|
||||||
|
.#.##...#.#..#....#.#.##.#.......#.....###.###.#.##.##...###.####......#
|
||||||
|
#.#####.#.##.#.#.##.#..#####......#...#...##.###.#..#.#.#..#.##.....###.
|
||||||
|
#....##.##....##.....#..#.#.#.#.#...###.#####....#..#.##.##.#.#.#.#.####
|
||||||
|
#....##.##....#...####....##..#.#.#.#.##.##.#..##....##....##..#...###..
|
||||||
|
##.#..##.#...#.##.#.#.##.#.#.#...#...#..##.###....#.##...###.#.#...####.
|
||||||
|
.############.#.#..#.###.###.######...#####.####.....#.#.###..##.#######
|
||||||
|
##...#.###..####..##...#...###...##..#.###...###.#.#..#.##..#######.###.
|
||||||
|
#..#.###..#..##..#..#.##.###..###....##..#.#..#....#.#.##..#.###.....#.#
|
||||||
|
#.#...#..#.##...###..##.##..###........#...##..#....###..##..#.#.###...#
|
||||||
|
##....#......##.####..##...###...##..#...#..#.#.##.#...####.#.#.####..#.
|
||||||
|
..#.#.###..##.##.#..####.###..####.....##.#...#.#.#...#.########.#.#....
|
||||||
|
#..#.##..#..##......##.##...#..#.#..#####..##.#.##..##.###.#.#..######.#
|
||||||
|
#..#..###.#..###.##..##....#..##..##...#.#...#..##..#####.###..###.####.
|
||||||
|
...#..##..##.#...#.....##..........#.##.#..#####..##..###..#...##.##..##
|
||||||
|
.#.#..##......#...#..#....#.######..#.#..##..#.......#.###.#.###..##....
|
||||||
|
..#.###.#.#.#.###.###..######..####...#..#.##.###..#....##..#.#.#.#..###
|
||||||
|
###.##.##.####.....####.##.##..##....###.#....###..###.##########.####..
|
||||||
|
#.#...#.###....##.#.#.##.#.#.#....#####...#.##..###.#.......#.##.#.###.#
|
||||||
|
.....##....#..#.....####.#.##..#.#..#....#.....#.######.##..#..###.#..#.
|
||||||
|
.........#...###..#....#...##.............###..###...#..##..####.###.##.
|
||||||
|
..#.#..#####.#.#..#.#...######.#.##..#...##.####...#...#.##..#.#.##.#...
|
||||||
|
#...#.#...##.#..##..#.####.#.#.######...###...#..#...#.##.#.#...#.###.##
|
||||||
|
.#####..#.#.##.#####...######.#..#.#.#.###...#...#.#.#.#.#..#..##.#...##
|
||||||
|
###.##.#.#.##...##..###....##.#.#..#..#...#.###.#.#.....#..##...#....#.#
|
||||||
|
##.#.##..#...###.#..#..###...#.##.#..#..####.#.#.##.#....#.#.#....#..###
|
||||||
|
.#.#.#...##.#.######.#.##.#.......#.#......#..#..#.#.####...###..#....#.
|
||||||
|
.#....####...#....#..#.##.######...####..#...#.####.####..#.##.#.#.###..
|
||||||
|
###.......#.###.##...##..#....#####..##.#...#..###..#......#...#.#.##..#
|
||||||
|
.#...##.#..##..#..###.##..#....#..#....##..#.##...###.##.#.####.##.#.###
|
||||||
|
..##.#.#.##.#.###.##.##...#.#....#.#..###..##....#.##...#...#.###.##.##.
|
||||||
|
#..#..##.##..#..#####..#.#.#.#.##....#####.#.#.....###.##....#.#...##..#
|
||||||
27
inputs/input24
Normal file
27
inputs/input24
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#.########################################################################################################################
|
||||||
|
#.v^<>^^.<^^<v>v>>>.<^<<v.^>vv>>^<<<v>.v<^v^<v<<^<^^<^<^v><^vv.v^^.>^><vv><^<.<^v<>.v<v..^>><v>.vvv.v>^^<^>.<<^<^<^>v.^^<#
|
||||||
|
#.^^<v>><<v><vv<>..<>v<^v><<>><>v.>v.^^<<.v.^<^<vv><v<<v><<^<>^v>v>><>v..v^<^.v><>^>><v<<>v^<<v<v>v.v<v>><<v>^v<v^...<<<>#
|
||||||
|
#><vv>>v>v<^>^^^^vv^<v^<<v<>^<^.^^>^<^vv>^v>><<^^<.>^>v<^v<.v.^<^^v.<.>.<^>v^>.v>>^vv^v.>>>v<<<<v.^^v<^^<^><<<<.^>.>vvv>>#
|
||||||
|
#<.vv>.><<.<^v.>v^v>><v>><<^vv>^v^>.><v>>><^><v<v^^vv>.v^^<v>vv<>v>^v.>>v^>..v<>^v.^>><.vv><^...<>^^>v>vvv>^<^<><v>v<^^^<#
|
||||||
|
#>^.^>vvv>vv>^^vv>v^^v>vv>v^v>^<v>>vvvv^>.v^<v^><^>vvv<>vv<^v<.<^v^>^vv^<><>.^.^>><<^^>^<v^>>>>v><<v^^>^^>>v^v.<^vv^<^v<>#
|
||||||
|
#><^>><vv^vvv.v><v<>^v>^<<<^^<><^<<v<>^<<v><<<v>><v<^^<vv<.>^v>^<v>.>v>>^^>^>><>.<<v<^><>>>^.<vv>.^^<.^^>>v.><<v<>><>v^><#
|
||||||
|
#>>^.<<v.^v>^^v.>v.vv^<<.v<v<..<<v^^>^v.><>v<^^<<.>v>v>v>^v>.<>v<><<^v><^>><^v>v^v>^vvv>>>..>^>>.><v><>.^^v.><<vv<.v>^^<.#
|
||||||
|
#>vv>^^.<>^v<^<<v^>v<^^v><>>>>v^vv>v<^v^><><^.<v^>.<^.v^>><vv>>vvv>^v<<<><vv<v^<<>v>>^v>^^^>^v><^^>^^^<<^^<v<<v<v>^^^<^>>#
|
||||||
|
#>.v^<<.vv<^v>^>>v<>v^v^^v^v<^^<<..<<^v<<<<^<v>^>.<>v<v<v<.<.v>vv^>><^.<.v<^<^v><v<v>.v.><<^>>v^.^vv.vv^.>^^>vv<>^..v>^v<#
|
||||||
|
#..v.>^><<>..<>.<^<<v>^^^^><<><<vv><^>v>^v<vv>v><vv.^<.<<<<v^v<>^^^vv>.>>>v^v<v<^.<v<<^.v<><<>>v<<<.>>v.^^>^^.>.<.>vv>^>>#
|
||||||
|
#>^^vv<<><<v<^.v>>v>^^^v^<v.^><<<<<v^v>v<<^v..^<.vv.^v>vvv>^v<..v<><<^<<vv<>>>>^>^^<>^<^<^^.vv>>^>^>^v^>.<^.<<.>v^>vv<.^<#
|
||||||
|
#<v^vv>^^v>vv>^.^>v>v^v>vv.>>.>v^v^>.^v<^.>^<<<v.>^>^^<>vv<.<^^<^v<^><v^v^.^<><v^^v^>.<vv^>v^v<v^><>^<vv>v<><^v<v.<<^.>^>#
|
||||||
|
#<>^<^<v><^^.^^>..^^>v>>>>^v<.<>>.<^v^>vvvvv>^<<.><^<v<.v<^><^^>vv<^<^<>v>v<>^^v>>^^>>v<^^<v>v^^^vvv<<<<<>>>v>^v.<^^>^>^<#
|
||||||
|
#>.<^v<.<^v.v>^.>>><^<<^^<<.<>><>>>^vvv<v<v<<^^vv<<<^v^v^vv<^v>>^^vv.^>^.v^^^>>v^>.<>.^^>v^^^^><^^>^>>.v<v^<^>^v^>^<<<v<<#
|
||||||
|
#>><><.>v^<>^^>.^>^v>^.^<v><><>.<v<^v>>>>v.<>>.^vv>v.vv.><vv^v>^<>>v>vv.v>v>v<><>>>^..^v>^^><..^..^..^vvv>><>v<>v<^<<>v<<#
|
||||||
|
#<vv^vvv><>v^v.<^v^^v<.<>v<>.^v^<<^<><.^vv<>^>>.v<<><vv<^^<>>v^.^v><v^^<>v.v<.>^^v^<<<^^<<v<^^^<<<<>^^v>><><<><>v>v<v.>^>#
|
||||||
|
#.<.^>^>^>^v..v>^.<v<^<<<^vvv>vv><^^v^<.>>.^<.^^<<>>^><<>>^^.^<<^^><^v<.><>.<<<.vvv>>vv^v<^v<>vv<<^v^^<v.v^<<^>v^>v<><vv<#
|
||||||
|
#.vvvv>>^>^<..^>>^>vv^.^>^<<v>^^v>v>^<>.>vv<v^>>>^.^<<^>>^>^>vvv><vv^^<^.^^.<^^v.<v<>^<<<v^>><<.^^^^>^>>>v<<>>v>v<>v<v><.#
|
||||||
|
#<<vv.<v>^^v<.>>^>^<>^><.<v^><>>.^<v^v<<.v>>.<>.v>^>^v><><^<><<<v^<><<v^..^v^v>^.><>>>v^.^>vv<<^>v<><.^^v<>vv>v^v<><^>>><#
|
||||||
|
#><>^v>v<>><vv>>v<>^<v>v^^>^v^>^^<v>v>^^v><<^v>>vv<^><>^>^^>>v^^<^<v>.^>v^vv^<.v>^v^.v^><><>>v.v^vv^<v>^>^><v>^>^>v>^v..<#
|
||||||
|
#>v<^^<^>.<>v<v<.^vv^>>v><^^v<^^>>^>^<^^>>>^<v<^v<>v<^>v>^>v^v>^.<<v^>vv<^<.><^><<^>v><^<v>^<^v>v^>><^vvv^>>v>>vv>v^>^><<#
|
||||||
|
#<vvv<><^.>v.^><v<^^<v><^<vvv.^..v^>...v^><<^^><^>^^vv>^v>v^<v<<>^>^^..<^<<v><<>.><<>^vvvv>v^><.^^>>v>>>^>>^<^<^<v^>vvv>>#
|
||||||
|
#><<<^^.^<.^.^^<>^.vv^^^<v^<<<vv<<>^<v<^>>v^>>v<<v^^.v^<.vv<v<><<.v><<^>>v><.v><v>v^^v^v<^><vvvvv<^.<<>v^.<>^.^><>^v><>^<#
|
||||||
|
#<.<>.>v^><<>^^<<vv>^>^v>>>v>v><^v><v.>>^<>>.<vv<<<v<v^<<vv^<.v^^>vv>>^<^<v<v<<>vv.><v..>>>.>^v<<vv><v^^^vv^^<>^>v<^^>v.>#
|
||||||
|
#<>^^<>>^v>v<<>^.>>^^^<<v>^vv^<^<.<<<vv>>v>^^<^v><><>.<>.^><<^^^>^vv><>v.<>v<.<v>>><v.^>^>vv<v>^<v^<<v^v>v..>^^<^^.><>^><#
|
||||||
|
########################################################################################################################.#
|
||||||
27
inputs/input24_dennis
Normal file
27
inputs/input24_dennis
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#.########################################################################################################################
|
||||||
|
#>^v<.<<^v^<><>>>^<vv>^>><<<^^.^v^<<v^v<v>^^>^^<^><^>.^>v<v<v.v<>vv<^^^vvv<.^v^<v^.^.>.<^<^>v^.v^v<>^vv^<<>>v^<<.<vvv^.<<#
|
||||||
|
#><^>><<vvv.v>^<..<v><v^^>>>v>>vv^^^<^^<><<>v>v<><><<^<<v>v.>.v>vv<>^>.^vv^^.<v<vv.<v<>>^>>><v<.>v>v^<v<>^<<<^v^<.v..v<^>#
|
||||||
|
#<v^.^>vv.^<^<>v^<^^^<^^>v<<>v><><^v^<v.v<^><<<^^^.>vv<.^<v<v<v^<v>^<v^<.><^^<>^v>..<v..>v^><>>^<.>.vv<<<.v.^^^^^>.<<.<v<#
|
||||||
|
#>.<<^>^v>>v<v<>>^v^>><>>v.^>.<>>^v<>.^<>^^^<vv<vv^^^v^^<<><v^^>>.v<v^v<.>^^.^>^v><vv<^^<^>>^v>^>^^v^v.<<^.vv<v..^^v.>>v>#
|
||||||
|
#>v^^>^^.>.^^<>><>v^^^<v>>>v^v^v^^<^<<^<<>><<^<<vv<<^>>>.<^v^><v<v>>v^>><vv..<v><vv^.>.v^vv>^><v.<vv>^vv^^>><v>v>v<v>>^><#
|
||||||
|
#>^<vvv^><^vvv>><^^vv^^>v<.v^<^<vv<><v<>^^^^<>^>v<^vv><v.<>>..>^^v<><>v.>>vv<><^^><>v<v<>vv^^>v><>>.v<v<>>>^^^v^v<<<^><^<#
|
||||||
|
#>^><v>>^.^><.^^^^<v>v<.v^>^^^<<<^<<v><><v>>>>v<v>vv<v><>.^><<^v<>^^v<.^^v<^>v<>v^.>.<<.>vv.^^vvv.<.v^>^><v^<^^^^>.^vv^^<#
|
||||||
|
#><v^vvv>^<v<>^>^<.><v<<<><v<<<^v^>^<v>>v<^<vv<v>v^..^>^^^^<.><<<>vvv>^vv^>v^<<>vv<<v^>^.v>.^<^^..>v<^<v<^>^^<><vv<.^v^.>#
|
||||||
|
#<^<><v.>.<<^>>v<^..<<.>>v<<^^>v.<v.<.v<.vv<^>^vvv>^>>v<.<>v^<<<<^<v>^<vv>v<<<^^>^^<<<>^>vv>>^.><>^^v^^><v.>v^^<>^^^^<v>>#
|
||||||
|
#<v.>^><^>>vv^vvvv^<>vv<<v<<v^v^v<><<^.^<><v^^<><.v<^>^v>^<^v^><^>v>^<<<v><v<<^^>v><v<<<<^.v^.<^<v<<>^>>><>vv<.^^..v>v<<>#
|
||||||
|
#<v<^>v<<^^>>v<^>^^>v>^>v.v<<<>v>><v<vv.v^<<.v<v>v<<^v<<.>^<v>^^>^..<>^^v.^><^vv><v<<>>vvv^^vv<<>^>^v^<^><<^v<.>^>><^^<^<#
|
||||||
|
#<<>>v^^>>^.<^^<^^^>^^>vv>>>>>v^vv><.v>v>v<^>><^<<v><^>^>^vv^vv^<v<<<v>><v.v>^^<<.^vvv<>vv<><^^^vv>v^.><^<^vv><<.vv^^^.v<#
|
||||||
|
#<.<v><vv>^<>>^>.^<<v>..^vvv^^v>^<>>v<<<..^vv>^<...^<<>.<^>^<.v><v.>^^.vv<<^<v.>v^v^^>.^^vv.^v^><<>^^^^.v<..>v^<>^<>>vvv>#
|
||||||
|
#<^<<v^v<^<.^v^>v^<^<.>^^v^<^>.<v>v>^^^.v><v><vv<<v<>v.<^><>.><vv><<^^.vv<.<^.vvvvvv^^^^<vvv.^<.>v.^v>^v>><v^v.>v^^v.<.^<#
|
||||||
|
#.<<^.<v<<^^<>v.<.>v.^^^<<^v>.v<>v<...>^<v.<v<<><>.v<^^^>.^v>vv^<^.>.^>>^>v.>v>.^^<v><v^<><^^v<v^^<<<>^.>v><<v<<v>.<^v<v>#
|
||||||
|
#>>><<^v<^>v^>><^^.<v<^<<<^.<v^>v<<^^^>>^^.^v^>v^<>^v.>^><^>.^^v>><<>v<v><^vv<><^v>.v><^><<v>.^>v^^<<^<>.>v<v^^v<v.>v..>>#
|
||||||
|
#.v>^^.<v.^^>><^v<vv>v<^<>><v>^^v<<v>>.<<v^v<^.v.<^>^vvv<vv^v>><>^v<^><v..<^<vv<<v<.<^^^<<>v^^v>v>>^^^>vvvv<^^<>.<^^^><^.#
|
||||||
|
#<^^<v<^<>>vv>v<<vv^v<^.<>><<v<<v>^^^^>^<^>>^vv^^<^vv^>vvv>v>^v.><^>^^>.^^v.<<v.v<^<<^v><vv^^^v^>><.^<>v><v<vv^^>>v^>>..>#
|
||||||
|
#<^>v^^vv>^><^^^^^^>>.v<^.<^<>^><^.v<v<>>v.^.v^<vv^^<<<><..>>><.v<vv>^v^.<>>v^v.<vv><v^<vv<<v<><.<<^^v><.>v<<>v<<^^>>vvv>#
|
||||||
|
#.><<>>><^vv^v.>.>.^.<>>^^^v^^><>v<><>>>><v<<v^<>^v^v>>^^v^.<>v>vvv>v>>.<>>^>>>>^>^>v<.><vv>>.>>v<>><<^><v.^<<..>.vvv^v<<#
|
||||||
|
#>^>^<^^v>^^^>v>.v><>^>^v^^.v.>>v>>v^^^>>>v><>.<vv.<<<.<^^<^>^>v<v>^<^v<><>><>.^vv>^>.^>>>^><<^>^v<<^<vv<vv^.^^<vv>>v.<>>#
|
||||||
|
#><<><v<<vv>^>.^.<<.>.<.v>^>><^>v<>v^.<><^v^>>v<^^<.<^<>.<vv<<>vvvv>vv>v.<<^v<.>v>^^<v><>.>v>^<^<^^..>v<v>v.^<^<^<vv<v><>#
|
||||||
|
#>>^^<^<v^<v<vv^>..^v.^<^>^.v><^vv^..v.<>v<<.<v..v>v>vvv^>^<v>vv.^.>^.^^>v<^>v>v><>>^^>.v^<<.<^>v^vv><.v..<.><<v<.<<.<vv>#
|
||||||
|
#><<>^<>><^.^^><v<<^<^^>>v><v.vv><v<<<<.<^<v>v><>v<<^<<>>^>^vv>v<v.vv>v>v>>>><..v^^vv>><<>>vv><>>.>v<<>v<v^vv<v<<v^>>v<^.#
|
||||||
|
#>.<<><<vv<^.v<v<v<^>>v><v.^>^v.<^v.^^^<<<<.<<v^v>^<.>^vv^<<^^>.v>>>.v^v<v<v><^>v.>>^^>^v>vv<>vv^^<.<.v>^^v>.^^v<^v^>^^v>#
|
||||||
|
########################################################################################################################.#
|
||||||
6
inputs/input24_test
Normal file
6
inputs/input24_test
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#.######
|
||||||
|
#>>.<^<#
|
||||||
|
#.<..<<#
|
||||||
|
#>v.><>#
|
||||||
|
#<^v^^>#
|
||||||
|
######.#
|
||||||
101
inputs/input25
Normal file
101
inputs/input25
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
22-00====1
|
||||||
|
1210=012020-1=
|
||||||
|
2=-221
|
||||||
|
1=020
|
||||||
|
1=2=0==12----=-
|
||||||
|
1===-22-=
|
||||||
|
101120212112-
|
||||||
|
2022-==20-=-12===2
|
||||||
|
1=20-200=22-1-1-2=
|
||||||
|
1-20021=21-
|
||||||
|
11--0-==0-1-22
|
||||||
|
2--0=---2=-
|
||||||
|
21=--=-01=-0=112-21
|
||||||
|
2=0200
|
||||||
|
1011021--0-=-10010
|
||||||
|
2=1=122-22=1---2
|
||||||
|
110-0--0
|
||||||
|
200
|
||||||
|
1=2
|
||||||
|
1==11=101-=-000=0==2
|
||||||
|
1200-022-=
|
||||||
|
1--0=02-2=21220022
|
||||||
|
10--
|
||||||
|
10===202=22=00=1
|
||||||
|
11022
|
||||||
|
1--222--
|
||||||
|
100
|
||||||
|
2-0
|
||||||
|
1=221==
|
||||||
|
1==21=22
|
||||||
|
2==0-=2
|
||||||
|
1==1=21=201-
|
||||||
|
12-0=1110-1=02-022
|
||||||
|
2-12=21=--0020=
|
||||||
|
10-1-0=0=01=0--=2--
|
||||||
|
2=1==-001=0=12
|
||||||
|
212=10002
|
||||||
|
10-=02200202=2==
|
||||||
|
1-21-0=-10
|
||||||
|
1-=12222112
|
||||||
|
1=1--12220=1
|
||||||
|
10-
|
||||||
|
1=-02
|
||||||
|
1=210
|
||||||
|
21==1=
|
||||||
|
1--==--11
|
||||||
|
1--21212-=--200-0-
|
||||||
|
1000010
|
||||||
|
202=012-11-100200
|
||||||
|
2=-21202200-=
|
||||||
|
11=1112=1020111
|
||||||
|
12=1002022-0
|
||||||
|
1122
|
||||||
|
1=-0-
|
||||||
|
1=1=20=0010-
|
||||||
|
12=2-0000---
|
||||||
|
1-
|
||||||
|
2-2=
|
||||||
|
12001==---1
|
||||||
|
2---=--=0012121100
|
||||||
|
10-10-11=1
|
||||||
|
1=112-2=0-0=0--=0
|
||||||
|
2=0=212122
|
||||||
|
102==21101=-==1
|
||||||
|
102
|
||||||
|
1=2-2-0000211
|
||||||
|
10-120-=00
|
||||||
|
2=-02112010111-0-
|
||||||
|
1-0=
|
||||||
|
112
|
||||||
|
1=2=
|
||||||
|
11=20
|
||||||
|
10-2-01-210
|
||||||
|
1-02122-2=-
|
||||||
|
1-22==0===0-0
|
||||||
|
10=--=011-
|
||||||
|
2101-=1-12
|
||||||
|
1==0=0=01
|
||||||
|
22110-=0=111
|
||||||
|
12---1-10-0-=1
|
||||||
|
2-2-=
|
||||||
|
1-=101--11=12=
|
||||||
|
2-0--02-01=1-10==
|
||||||
|
2=--=200=12=110
|
||||||
|
12=
|
||||||
|
2--=
|
||||||
|
20212
|
||||||
|
2102-2
|
||||||
|
2=202102
|
||||||
|
2=1=
|
||||||
|
1101011-=1222-
|
||||||
|
11
|
||||||
|
202
|
||||||
|
102=10001=
|
||||||
|
101001
|
||||||
|
1====11=0=12
|
||||||
|
2211001
|
||||||
|
11-2-
|
||||||
|
1-00
|
||||||
|
11=1-1--
|
||||||
|
2=
|
||||||
13
inputs/input25_test
Normal file
13
inputs/input25_test
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
1=-0-2
|
||||||
|
12111
|
||||||
|
2=0=
|
||||||
|
21
|
||||||
|
2=01
|
||||||
|
111
|
||||||
|
20012
|
||||||
|
112
|
||||||
|
1=-1=
|
||||||
|
1-12
|
||||||
|
12
|
||||||
|
1=
|
||||||
|
122
|
||||||
Loading…
Reference in New Issue
Block a user