Compare commits
No commits in common. "1d5bec6bde7c626ec3e677848dee3ea89c753da8" and "a82057d89c33400cedb91bb9e4dfd92afde5a059" have entirely different histories.
1d5bec6bde
...
a82057d89c
182
d16_old.py
182
d16_old.py
@ -1,182 +0,0 @@
|
|||||||
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)
|
|
||||||
276
day16.py
276
day16.py
@ -1,151 +1,124 @@
|
|||||||
import heapq
|
from collections import deque
|
||||||
import itertools
|
from itertools import product
|
||||||
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) -> None:
|
def __init__(self, name: str, flowrate: int):
|
||||||
self.__name = name
|
self.name: str = name
|
||||||
self.__flowrate = flowrate
|
self.flowrate: int = flowrate
|
||||||
self.neighbours = {}
|
self.tunnels: set = set()
|
||||||
|
|
||||||
@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__()
|
|
||||||
|
|
||||||
|
|
||||||
def get_most_pressure_release_solo(root: Valve, remaining_minutes: int = 30, visited: set = None) -> int:
|
class Tunnel:
|
||||||
if visited is None:
|
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()
|
visited = set()
|
||||||
visited.add(root)
|
queue.append((0, valve))
|
||||||
|
while queue:
|
||||||
my_flowrate = 0
|
d, v = queue.popleft()
|
||||||
if root.flowrate > 0:
|
if v.name in visited:
|
||||||
remaining_minutes -= 1
|
|
||||||
my_flowrate = root.flowrate * remaining_minutes
|
|
||||||
|
|
||||||
max_flowrate = 0
|
|
||||||
for n, d in root.neighbours.items():
|
|
||||||
if n 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))
|
||||||
|
|
||||||
if remaining_minutes <= d + 1:
|
return tunnels
|
||||||
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_mode_pressure_release_double(root_me: Valve, root_ele: Valve, r_min_me: int = 26, r_min_ele: int = 26, visited: set = None) -> int:
|
def get_max_flow(valve: Valve, open_valves: list, time_remaining: int = 30, depth: int = 0) -> int:
|
||||||
dp_key = root_me.name + root_ele.name + "%02d" % r_min_me + "%02d" % r_min_ele + "".join(v.name for v in sorted(visited))
|
max_flow = 0
|
||||||
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]
|
||||||
|
|
||||||
my_flowrate = 0
|
if time_remaining_1 <= 0 and time_remaining_2 <= 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
|
||||||
|
|
||||||
max_flowrate = 0
|
ov1 = {t for t in valve1.tunnels if t.target.name not in open_valves and t.length < time_remaining_1 - 2}
|
||||||
rem_list = [x for x in root_me.neighbours.keys() if x not in visited]
|
ov2 = {t for t in valve2.tunnels if t.target.name not in open_valves and t.length < time_remaining_2 - 2}
|
||||||
if len(rem_list) == 1:
|
|
||||||
if root_me.neighbours[rem_list[0]] < root_ele.neighbours[rem_list[0]]:
|
if not ov1 and not ov2:
|
||||||
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())
|
return 0
|
||||||
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())
|
if not ov1:
|
||||||
else:
|
ov1 = {Tunnel(valve1, 99)}
|
||||||
max_prod = len(rem_list) ** 2
|
|
||||||
cur_prod = 0
|
if not ov2:
|
||||||
for v1, v2 in itertools.product(rem_list, repeat=2):
|
ov2 = {Tunnel(valve2, 99)}
|
||||||
if len(visited) == 1:
|
|
||||||
cur_prod += 1
|
permut = product(ov1, ov2)
|
||||||
print("Iter (%d/%d)" % (cur_prod, max_prod))
|
|
||||||
if v1 == v2:
|
max_flow = 0
|
||||||
|
for v1, v2 in permut:
|
||||||
|
if v1.target.name == v2.target.name:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
me, ele = v1, v2
|
this_open_flow = 0
|
||||||
if r_min_me <= root_me.neighbours[me] + 1:
|
|
||||||
me = root_me
|
|
||||||
|
|
||||||
if r_min_ele <= root_ele.neighbours[ele] + 1:
|
t1 = valve1
|
||||||
ele = root_ele
|
if v1.length + 2 <= time_remaining_1:
|
||||||
|
this_open_flow += v1.target.flowrate * (time_remaining_1 - v1.length - 1)
|
||||||
|
t1 = v1.target
|
||||||
|
|
||||||
if me == root_me and ele == root_ele:
|
t2 = valve2
|
||||||
continue
|
if v2.length + 2 <= time_remaining_2:
|
||||||
|
this_open_flow += v2.target.flowrate * (time_remaining_2 - v2.length - 1)
|
||||||
|
t2 = v2.target
|
||||||
|
|
||||||
n_flowrate = get_mode_pressure_release_double(
|
this_flow_rate = get_max_flow_double(
|
||||||
me, ele,
|
t1,
|
||||||
r_min_me - (root_me.neighbours[me] if me in root_me.neighbours else 1),
|
t2,
|
||||||
r_min_ele - (root_ele.neighbours[ele] if ele in root_ele.neighbours else 1),
|
sorted(open_valves + [v1.target.name, v2.target.name]),
|
||||||
visited.copy()
|
DP,
|
||||||
|
time_remaining_1 - v1.length - 1,
|
||||||
|
time_remaining_2 - v2.length - 1,
|
||||||
|
depth + 1
|
||||||
)
|
)
|
||||||
if n_flowrate > max_flowrate:
|
|
||||||
max_flowrate = n_flowrate
|
|
||||||
|
|
||||||
if n_flowrate == 1671:
|
if this_flow_rate + this_open_flow > max_flow:
|
||||||
break
|
max_flow = this_flow_rate + this_open_flow
|
||||||
|
|
||||||
DP[dp_key] = my_flowrate + max_flowrate
|
DP[dp_key] = max_flow
|
||||||
DP[dp_key2] = my_flowrate + max_flowrate
|
DP[dp_key2] = max_flow
|
||||||
return my_flowrate + max_flowrate
|
return max_flow
|
||||||
|
|
||||||
|
|
||||||
DP = {}
|
|
||||||
|
|
||||||
|
|
||||||
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"),
|
||||||
@ -159,54 +132,49 @@ class Day(AOCDay):
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
def parse_input(self) -> Valve:
|
def get_valve_graph(self) -> Valve:
|
||||||
n_cache = {}
|
|
||||||
valves = {}
|
valves = {}
|
||||||
|
tmp_tunnels = {}
|
||||||
for line in self.getInput():
|
for line in self.getInput():
|
||||||
name, flowrate, neighbours = self.input_regexp.match(line).groups()
|
p = line.split(" ")
|
||||||
valves[name] = Valve(name, int(flowrate))
|
valve_name = p[1]
|
||||||
n_cache[name] = neighbours.split(", ")
|
flowrate = int(p[4][5:-1])
|
||||||
|
tunnels = "".join(p[9:]).split(",")
|
||||||
|
valves[valve_name] = Valve(valve_name, flowrate)
|
||||||
|
tmp_tunnels[valve_name] = tunnels
|
||||||
|
|
||||||
for valve, neighbours in n_cache.items():
|
for name, tunnels in tmp_tunnels.items():
|
||||||
for n in neighbours:
|
valves[name].tunnels = {Tunnel(valves[t]) for t in tunnels}
|
||||||
valves[valve].neighbours[valves[n]] = 1
|
|
||||||
|
|
||||||
for valve in valves.values():
|
for valve in valves.values():
|
||||||
if valve.flowrate != 0:
|
tunnels = set()
|
||||||
|
queue = deque()
|
||||||
|
visited = set()
|
||||||
|
queue.append((0, valve))
|
||||||
|
while queue:
|
||||||
|
d, v = queue.popleft()
|
||||||
|
if v in visited:
|
||||||
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))
|
||||||
|
|
||||||
for n_set in valve.neighbours.keys():
|
tmp_tunnels[valve.name] = tunnels
|
||||||
del n_set.neighbours[valve]
|
|
||||||
for n_get in valve.neighbours.keys():
|
|
||||||
if n_get == n_set:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if n_get in n_set.neighbours:
|
for name, tunnels in tmp_tunnels.items():
|
||||||
continue
|
valves[name].tunnels = tunnels
|
||||||
|
|
||||||
n_set.neighbours[n_get] = valve.neighbours[n_set] + valve.neighbours[n_get]
|
return valves["AA"]
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
v_set.neighbours[v_get] = v_set.shortest_path_to(v_get)
|
|
||||||
|
|
||||||
for n in list(valves['AA'].neighbours.keys()):
|
|
||||||
if n.flowrate == 0:
|
|
||||||
del valves['AA'].neighbours[n]
|
|
||||||
|
|
||||||
return valves['AA']
|
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
return get_most_pressure_release_solo(self.parse_input())
|
return get_max_flow(self.get_valve_graph(), [])
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
global DP
|
cache = Cache()
|
||||||
DP = {}
|
root = self.get_valve_graph()
|
||||||
root_valve = self.parse_input()
|
return get_max_flow_double(root, root, [], cache)
|
||||||
return get_mode_pressure_release_double(root_valve, root_valve, visited={root_valve})
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
373
day22.py
373
day22.py
@ -1,40 +1,231 @@
|
|||||||
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, GridTransformation
|
from tools.grid import Grid
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
FACING = [
|
FACING = [
|
||||||
Coordinate(1, 0, 0),
|
Coordinate(1, 0),
|
||||||
Coordinate(0, 1, 0),
|
Coordinate(0, 1),
|
||||||
Coordinate(-1, 0, 0),
|
Coordinate(-1, 0),
|
||||||
Coordinate(0, -1, 0)
|
Coordinate(0, -1)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
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 walk(board: Grid, pos: Coordinate, directions: list) -> (Coordinate, int):
|
def get_cube_conn_dict(cube_conn: tuple, c_size: int) -> dict:
|
||||||
face = 0
|
conn_dict = {}
|
||||||
|
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:
|
||||||
|
next_pos, next_face = connections[(pos.x, pos.y, face)]
|
||||||
|
print("wrapping from", pos, "to", next_pos, "facing", next_face)
|
||||||
|
else:
|
||||||
match face:
|
match face:
|
||||||
case 0:
|
case 0:
|
||||||
next_pos = Coordinate(0, next_pos.y, 0)
|
next_pos = Coordinate(0, next_pos.y)
|
||||||
case 1:
|
case 1:
|
||||||
next_pos = Coordinate(next_pos.x, 0, 0)
|
next_pos = Coordinate(next_pos.x, 0)
|
||||||
case 2:
|
case 2:
|
||||||
next_pos = Coordinate(board.maxX, next_pos.y, 0)
|
next_pos = Coordinate(board.maxX, next_pos.y)
|
||||||
case 3:
|
case 3:
|
||||||
next_pos = Coordinate(next_pos.x, board.maxY, 0)
|
next_pos = Coordinate(next_pos.x, board.maxY)
|
||||||
while board.get(next_pos) is None:
|
while board.get(next_pos) is None:
|
||||||
next_pos += FACING[face]
|
next_pos += FACING[face]
|
||||||
|
|
||||||
@ -51,121 +242,29 @@ def walk(board: Grid, pos: Coordinate, directions: list) -> (Coordinate, int):
|
|||||||
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"),
|
||||||
(55364, "input22_dennis"),
|
(None, "input22"),
|
||||||
(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()
|
||||||
board = Grid.from_str("/".join(map_lines), default=None, translate={' ': None, '#': False, '.': True}, mode3d=True)
|
for y, map_line in enumerate(map_lines):
|
||||||
for x in board.rangeX():
|
for x, v in enumerate(map_line):
|
||||||
if board.get(Coordinate(x, 0, 0)) is not None:
|
if v in ['#', '.']:
|
||||||
start_pos = Coordinate(x, 0, 0)
|
c = Coordinate(x, y)
|
||||||
break
|
if start_pos is None and v == '.':
|
||||||
|
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'
|
||||||
@ -173,43 +272,29 @@ 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, directions, start_pos
|
return board_map, directions, start_pos
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
board, directions, start_position = self.get_map_and_directions()
|
board_map, directions, start_position = self.get_map_and_directions()
|
||||||
finish, face = walk(board, start_position, directions)
|
finish, face = walk(board_map, 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, directions, start_position = self.get_map_and_directions()
|
board_map, directions, start_position = self.get_map_and_directions()
|
||||||
board.shift(shift_x=1, shift_y=1)
|
conn = identify_cube(board_map)
|
||||||
start_position += Coordinate(1, 1, 0)
|
for x in board_map.rangeX():
|
||||||
fold(board, start_position)
|
c = Coordinate(x, 0)
|
||||||
finish, face = cube_walk(board, Coordinate(1, 1, 0), directions)
|
if board_map.get(c) is not None:
|
||||||
|
start_position = c
|
||||||
orig_board, _, _ = self.get_map_and_directions()
|
break
|
||||||
c_size = 4 if orig_board.maxX < 50 else 50 # account for test case
|
print(board_map.minX, board_map.minY, board_map.maxX, board_map.maxY)
|
||||||
for x in range(0, orig_board.maxX + 1, c_size):
|
print(start_position)
|
||||||
for y in range(0, orig_board.maxY + 1, c_size):
|
print(board_map.get(Coordinate(4, 0)))
|
||||||
check_pos = finish - Coordinate(1, 1, 0)
|
print(conn)
|
||||||
check_face = face
|
board_map.print(true_char='.')
|
||||||
sub_board = orig_board.sub_grid(x, y, x + c_size - 1, y + c_size - 1, 0, 0)
|
finish, face = walk(board_map, start_position, directions, 0, conn)
|
||||||
if len(sub_board.getActiveCells()) == 0:
|
print(finish, face)
|
||||||
continue
|
print(get_password_from_coord(finish, face))
|
||||||
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,18 +52,16 @@ 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()), translate={'#': True, '.': False})
|
map = Grid.from_str("/".join(self.getInput()), true_char='#')
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
if not move_elfs(map, i):
|
if not move_elfs(map, i):
|
||||||
@ -73,7 +71,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()), translate={'#': True, '.': False})
|
map = Grid.from_str("/".join(self.getInput()), true_char='#')
|
||||||
round = 0
|
round = 0
|
||||||
|
|
||||||
while move_elfs(map, round):
|
while move_elfs(map, round):
|
||||||
|
|||||||
109
day24.py
109
day24.py
@ -1,109 +0,0 @@
|
|||||||
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
58
day25.py
@ -1,58 +0,0 @@
|
|||||||
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)
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,72 +0,0 @@
|
|||||||
#.##......#...#.###......###.........####.##...#.###...####.#....#.#.#.#
|
|
||||||
..#.###..##.##.#.#.....#.###..###.#..........#..#...##..####.#.#..#..##.
|
|
||||||
#..#.###...##.....##.#.#####.#..##.....##...#.#.#....##.#..###.###....#.
|
|
||||||
#.###...###.#.##.#..#..#.##..##...##.#..##..#.##.##....#######...#..#...
|
|
||||||
....#.#.###...#.#..###.#.#..##....#####.#...##..#.#...##.##.....###..#.#
|
|
||||||
..###.#.#..#####..##.##....###......##.##..####.#.###....######.#.#.##..
|
|
||||||
#...###.##.##..###.####.####.#...###..##...#.#..#####.#...##...#..##..##
|
|
||||||
##.####....###.#####..#.#.###.##.#...#..##.##.###..#...##.#.#..###...#..
|
|
||||||
####...##..#..####...##.##..##.##..#.##.......#..#.##.#...###..######.##
|
|
||||||
.#.##.#.###.##.##........####.#...#.##...##..##.....#..##.#.###...######
|
|
||||||
#.......#...#####.#...#.###...####..####....##..###.##..##..######....#.
|
|
||||||
.##.###..#....#.#.#####.###..#.##......#...##..##...#..#.##.#...##..#..#
|
|
||||||
##.###......####.#..#####.....#..##.####.#.#....##...##.#.#.##...#.#.#..
|
|
||||||
.#.##..###.#.......#..##.##.#.#.........#.##.##.......##....##..#..#....
|
|
||||||
###..####.##..##..#....#..#..#.#.##..#........#...##.##.#.##...#.#...#.#
|
|
||||||
..#.#####.#..###.#.##..#..#...#.#...#...#..##.#.#..##..#.#...####..#...#
|
|
||||||
#...#####..#.####.#.##.##.#...##.#...#.....##.....#..#.###..#.#...#..#..
|
|
||||||
.##########...#..#..#......#.###.#......#..#.#..#..#.#..#..#.#.###.#...#
|
|
||||||
.##..#.##.###.#...##.#...#.##.#.##..##...#.#..#...#.....#.######..#.#.##
|
|
||||||
.#.#.....###......#.#.##.#..#...#....##.#..#.###...#.....###.##.####..##
|
|
||||||
..#..#.#...#.###..#..####....##.#........##..###..####....###..###.###..
|
|
||||||
#..##.###.#.#..#..#.##....#...#.#.###..#.#.....###..##..#####...##.#..#.
|
|
||||||
#.#......##.#.#.#.###.#.#...###..######.###.##.#.#....#####..#.#..###.##
|
|
||||||
........##.##.##..##.#.###.#..#.########.....#.#.##.##.#......########.#
|
|
||||||
#..#.#.#...#..#.#....###.....###.###.#.##....##...#...#..#.#..##.###.###
|
|
||||||
.#...####.#.#....#.####..#...##.#.##...#.#.####.#...#..##.###...#.###..#
|
|
||||||
......#...#..##.##.###.#..#.....######..##.####.#......#..##.......####.
|
|
||||||
...###.#..#.....#..#.####...#..#...#...##..#...##.##....####......###..#
|
|
||||||
#.###...#.##.######.#...#...##..#.#..##.#.#....#####.####.#.#......#..##
|
|
||||||
##.....#..####.#.#.###...#..#..#..#..#.#.#....###..##..#.#.#....#..#.##.
|
|
||||||
.#.#.....####.#.#...........#.#.##.####...#.#...#..#.#..####.#..#.#.##.#
|
|
||||||
...#..#...#.#.###..#.#..##...##.#.#..#.#####.#.##.###.#......#..##.#.###
|
|
||||||
...#....##########.######...#.....#..#.##...###..#.####.#.####..##..##..
|
|
||||||
#.##....#..#...####.......##.#..##.#.#..#######.....#.#.#.##..##..#.#...
|
|
||||||
###..##..#..#.#..###..#.#.#..###....##..#.#.....##..#..#....#....###.#.#
|
|
||||||
##.#.#..#.#######.......#..#.#.#...#..#.#..######..##..........##....#..
|
|
||||||
......##..#######.#..#...#.#####.#.#.#..#.####.####..##.##.#.##....#....
|
|
||||||
...#.###...######.#....#.#...###.##.#.#.###..#.#...####.#....#...#.#..#.
|
|
||||||
#.#...#.###..#####.###..##.#....#...#.##...#..#...####.#...#.##.#..#.#.#
|
|
||||||
##.#..##....##..#..######....##.##.....##..##....###....#####.#.##....##
|
|
||||||
#..#.#..#..###.##..#....#.##.#####.###.#.##.#..#.#..#####..###..###.#.##
|
|
||||||
.#.##...#.#..#....#.#.##.#.......#.....###.###.#.##.##...###.####......#
|
|
||||||
#.#####.#.##.#.#.##.#..#####......#...#...##.###.#..#.#.#..#.##.....###.
|
|
||||||
#....##.##....##.....#..#.#.#.#.#...###.#####....#..#.##.##.#.#.#.#.####
|
|
||||||
#....##.##....#...####....##..#.#.#.#.##.##.#..##....##....##..#...###..
|
|
||||||
##.#..##.#...#.##.#.#.##.#.#.#...#...#..##.###....#.##...###.#.#...####.
|
|
||||||
.############.#.#..#.###.###.######...#####.####.....#.#.###..##.#######
|
|
||||||
##...#.###..####..##...#...###...##..#.###...###.#.#..#.##..#######.###.
|
|
||||||
#..#.###..#..##..#..#.##.###..###....##..#.#..#....#.#.##..#.###.....#.#
|
|
||||||
#.#...#..#.##...###..##.##..###........#...##..#....###..##..#.#.###...#
|
|
||||||
##....#......##.####..##...###...##..#...#..#.#.##.#...####.#.#.####..#.
|
|
||||||
..#.#.###..##.##.#..####.###..####.....##.#...#.#.#...#.########.#.#....
|
|
||||||
#..#.##..#..##......##.##...#..#.#..#####..##.#.##..##.###.#.#..######.#
|
|
||||||
#..#..###.#..###.##..##....#..##..##...#.#...#..##..#####.###..###.####.
|
|
||||||
...#..##..##.#...#.....##..........#.##.#..#####..##..###..#...##.##..##
|
|
||||||
.#.#..##......#...#..#....#.######..#.#..##..#.......#.###.#.###..##....
|
|
||||||
..#.###.#.#.#.###.###..######..####...#..#.##.###..#....##..#.#.#.#..###
|
|
||||||
###.##.##.####.....####.##.##..##....###.#....###..###.##########.####..
|
|
||||||
#.#...#.###....##.#.#.##.#.#.#....#####...#.##..###.#.......#.##.#.###.#
|
|
||||||
.....##....#..#.....####.#.##..#.#..#....#.....#.######.##..#..###.#..#.
|
|
||||||
.........#...###..#....#...##.............###..###...#..##..####.###.##.
|
|
||||||
..#.#..#####.#.#..#.#...######.#.##..#...##.####...#...#.##..#.#.##.#...
|
|
||||||
#...#.#...##.#..##..#.####.#.#.######...###...#..#...#.##.#.#...#.###.##
|
|
||||||
.#####..#.#.##.#####...######.#..#.#.#.###...#...#.#.#.#.#..#..##.#...##
|
|
||||||
###.##.#.#.##...##..###....##.#.#..#..#...#.###.#.#.....#..##...#....#.#
|
|
||||||
##.#.##..#...###.#..#..###...#.##.#..#..####.#.#.##.#....#.#.#....#..###
|
|
||||||
.#.#.#...##.#.######.#.##.#.......#.#......#..#..#.#.####...###..#....#.
|
|
||||||
.#....####...#....#..#.##.######...####..#...#.####.####..#.##.#.#.###..
|
|
||||||
###.......#.###.##...##..#....#####..##.#...#..###..#......#...#.#.##..#
|
|
||||||
.#...##.#..##..#..###.##..#....#..#....##..#.##...###.##.#.####.##.#.###
|
|
||||||
..##.#.#.##.#.###.##.##...#.#....#.#..###..##....#.##...#...#.###.##.##.
|
|
||||||
#..#..##.##..#..#####..#.#.#.#.##....#####.#.#.....###.##....#.#...##..#
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
#.########################################################################################################################
|
|
||||||
#.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..>^^<^^.><>^><#
|
|
||||||
########################################################################################################################.#
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
#.########################################################################################################################
|
|
||||||
#>^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>#
|
|
||||||
########################################################################################################################.#
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
#.######
|
|
||||||
#>>.<^<#
|
|
||||||
#.<..<<#
|
|
||||||
#>v.><>#
|
|
||||||
#<^v^^>#
|
|
||||||
######.#
|
|
||||||
101
inputs/input25
101
inputs/input25
@ -1,101 +0,0 @@
|
|||||||
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=
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
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