Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3732e70ef7 | ||
|
b0cc6b4a46 | ||
|
8c24b9f9e2 | ||
|
dca6f6a08f | ||
|
8d7a20f575 | ||
|
3934dfd152 | ||
|
b656e8929e | ||
|
c9c69f479b | ||
|
72ebcfff1f | ||
|
dd72bb3238 | ||
|
c1dd74c57d | ||
|
1bf2de62c7 | ||
|
df808bc98a | ||
|
f46e190e98 | ||
|
7f4a34b2d7 |
511
2022/day19.py
511
2022/day19.py
@@ -1,17 +1,14 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
import heapq
|
|
||||||
import math
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
from typing import Literal
|
||||||
from collections import defaultdict
|
|
||||||
from typing import Literal, TypedDict
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import parse
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
Reagent = Literal["ore", "clay", "obsidian", "geode"]
|
||||||
REAGENTS: tuple[Reagent] = (
|
REAGENTS: tuple[Reagent, ...] = (
|
||||||
"ore",
|
"ore",
|
||||||
"clay",
|
"clay",
|
||||||
"obsidian",
|
"obsidian",
|
||||||
@@ -20,23 +17,6 @@ REAGENTS: tuple[Reagent] = (
|
|||||||
|
|
||||||
IntOfReagent = dict[Reagent, int]
|
IntOfReagent = dict[Reagent, int]
|
||||||
|
|
||||||
lines = sys.stdin.read().splitlines()
|
|
||||||
|
|
||||||
blueprints: list[dict[Reagent, IntOfReagent]] = [
|
|
||||||
{
|
|
||||||
"ore": {"ore": 4},
|
|
||||||
"clay": {"ore": 2},
|
|
||||||
"obsidian": {"ore": 3, "clay": 14},
|
|
||||||
"geode": {"ore": 2, "obsidian": 7},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ore": {"ore": 2},
|
|
||||||
"clay": {"ore": 3},
|
|
||||||
"obsidian": {"ore": 3, "clay": 8},
|
|
||||||
"geode": {"ore": 3, "obsidian": 12},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
robots: IntOfReagent
|
robots: IntOfReagent
|
||||||
@@ -64,11 +44,6 @@ class State:
|
|||||||
and self.reagents == other.reagents
|
and self.reagents == other.reagents
|
||||||
)
|
)
|
||||||
|
|
||||||
def __lt__(self, other) -> bool:
|
|
||||||
return isinstance(other, State) and tuple(
|
|
||||||
(self.robots[r], self.reagents[r]) for r in REAGENTS
|
|
||||||
) > tuple((other.robots[r], other.reagents[r]) for r in REAGENTS)
|
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return hash(tuple((self.robots[r], self.reagents[r]) for r in REAGENTS))
|
return hash(tuple((self.robots[r], self.reagents[r]) for r in REAGENTS))
|
||||||
|
|
||||||
@@ -89,399 +64,123 @@ def dominates(lhs: State, rhs: State):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
MAX_TIME = 24
|
lines = sys.stdin.read().splitlines()
|
||||||
blueprint = blueprints[1]
|
|
||||||
|
|
||||||
# parents: dict[State, tuple[State | None, int]] = {State(): (None, 0)}
|
blueprints: list[dict[Reagent, IntOfReagent]] = []
|
||||||
# queue = [(0, State())]
|
for line in lines:
|
||||||
# visited: set[State] = set()
|
r = parse.parse(
|
||||||
# at_time: dict[int, list[State]] = defaultdict(lambda: [])
|
"Blueprint {}: "
|
||||||
|
"Each ore robot costs {:d} ore. "
|
||||||
|
"Each clay robot costs {:d} ore. "
|
||||||
|
"Each obsidian robot costs {:d} ore and {:d} clay. "
|
||||||
|
"Each geode robot costs {:d} ore and {:d} obsidian.",
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
|
||||||
# while queue:
|
blueprints.append(
|
||||||
# time, state = heapq.heappop(queue)
|
{
|
||||||
# if state in visited:
|
"ore": {"ore": r[1]},
|
||||||
# continue
|
"clay": {"ore": r[2]},
|
||||||
|
"obsidian": {"ore": r[3], "clay": r[4]},
|
||||||
# print(time, state)
|
"geode": {"ore": r[5], "obsidian": r[6]},
|
||||||
|
}
|
||||||
# visited.add(state)
|
)
|
||||||
|
|
||||||
# at_time[time].append(state)
|
|
||||||
|
|
||||||
# if time > MAX_TIME:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# if len(queue) % 200 == 0:
|
|
||||||
# print(len(queue), len(visited), time)
|
|
||||||
|
|
||||||
# can_build_any: bool = False
|
|
||||||
# for reagent in REAGENTS:
|
|
||||||
# needed = blueprint[reagent]
|
|
||||||
|
|
||||||
# if any(state.robots[r] == 0 for r in needed):
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# time_to_complete = max(
|
|
||||||
# max(
|
|
||||||
# math.ceil((needed[r] - state.reagents[r]) / state.robots[r])
|
|
||||||
# for r in needed
|
|
||||||
# ),
|
|
||||||
# 0,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# # if time_to_complete != 0:
|
|
||||||
# # continue
|
|
||||||
|
|
||||||
# if time + time_to_complete + 1 > MAX_TIME:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# wait = time_to_complete + 1
|
|
||||||
|
|
||||||
# reagents = {
|
|
||||||
# r: state.reagents[r] + wait * state.robots[r] - needed.get(r, 0)
|
|
||||||
# for r in REAGENTS
|
|
||||||
# }
|
|
||||||
|
|
||||||
# robots = state.robots.copy()
|
|
||||||
# robots[reagent] += 1
|
|
||||||
|
|
||||||
# state_2 = State(reagents=reagents, robots=robots)
|
|
||||||
|
|
||||||
# if state_2 in visited:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# if any(dominates(state_v, state_2) for state_v in at_time[time + wait]):
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# # print(time + wait)
|
|
||||||
# # if any(dominates(state_3, state_2) for state_3 in at_time[time + wait]):
|
|
||||||
# # print("?")
|
|
||||||
# # continue
|
|
||||||
|
|
||||||
# if state_2 not in parents or parents[state_2][1] > time + wait:
|
|
||||||
# parents[state_2] = (state, time + wait)
|
|
||||||
# heapq.heappush(queue, (time + wait, state_2))
|
|
||||||
# can_build_any = True
|
|
||||||
# at_time[time + wait].append(state_2)
|
|
||||||
|
|
||||||
# if not can_build_any:
|
|
||||||
# state_2 = State(
|
|
||||||
# reagents={
|
|
||||||
# r: state.reagents[r] + state.robots[r] * (MAX_TIME - time)
|
|
||||||
# for r in REAGENTS
|
|
||||||
# },
|
|
||||||
# robots=state.robots,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# if state_2 in visited:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# if state_2 not in parents or parents[state_2][1] > time + wait:
|
|
||||||
# parents[state_2] = (state, MAX_TIME)
|
|
||||||
# heapq.heappush(queue, (MAX_TIME, state_2))
|
|
||||||
|
|
||||||
# print(len(visited))
|
|
||||||
# print(max(state.reagents["geode"] for state in visited))
|
|
||||||
|
|
||||||
# exit()
|
|
||||||
|
|
||||||
# while states:
|
|
||||||
# state = states.pop()
|
|
||||||
# processed.append(state)
|
|
||||||
|
|
||||||
# if state.time > MAX_TIME:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# if len(states) % 100 == 0:
|
|
||||||
# print(len(states), len(processed), min((s.time for s in states), default=1))
|
|
||||||
|
|
||||||
# can_build_any: bool = False
|
|
||||||
# for reagent in REAGENTS:
|
|
||||||
# needed = blueprint[reagent]
|
|
||||||
|
|
||||||
# if any(state.robots[r] == 0 for r in needed):
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# time_to_complete = max(
|
|
||||||
# max(
|
|
||||||
# math.ceil((needed[r] - state.reagents[r]) / state.robots[r])
|
|
||||||
# for r in needed
|
|
||||||
# ),
|
|
||||||
# 0,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# if state.time + time_to_complete + 1 > MAX_TIME:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# wait = time_to_complete + 1
|
|
||||||
|
|
||||||
# reagents = {
|
|
||||||
# r: state.reagents[r] + wait * state.robots[r] - needed.get(r, 0)
|
|
||||||
# for r in REAGENTS
|
|
||||||
# }
|
|
||||||
|
|
||||||
# robots = state.robots.copy()
|
|
||||||
# robots[reagent] += 1
|
|
||||||
|
|
||||||
# can_build_any = True
|
|
||||||
# state_2 = State(time=state.time + wait, reagents=reagents, robots=robots)
|
|
||||||
# # print(f"{state} -> {state_2}")
|
|
||||||
# states.add(state_2)
|
|
||||||
|
|
||||||
# if not any(dominates(s2, state_2) for s2 in states):
|
|
||||||
# states.add(state)
|
|
||||||
|
|
||||||
# # print(f"can build {reagent} in {time_to_complete}")
|
|
||||||
|
|
||||||
# if not can_build_any:
|
|
||||||
# states.add(
|
|
||||||
# State(
|
|
||||||
# time=MAX_TIME + 1,
|
|
||||||
# reagents={
|
|
||||||
# r: state.reagents[r] + state.robots[r] * (MAX_TIME - state.time)
|
|
||||||
# for r in REAGENTS
|
|
||||||
# },
|
|
||||||
# robots=state.robots,
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
# if len(states) % 1000 == 0:
|
|
||||||
# print("filtering")
|
|
||||||
# states = {
|
|
||||||
# s1
|
|
||||||
# for s1 in states
|
|
||||||
# if not any(dominates(s2, s1) for s2 in states if s2 is not s1)
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # if len(states) > 4:
|
|
||||||
# # break
|
|
||||||
|
|
||||||
# # break
|
|
||||||
|
|
||||||
# print(len(processed))
|
|
||||||
# print(max(state.reagents["geode"] for state in processed))
|
|
||||||
|
|
||||||
# exit()
|
|
||||||
|
|
||||||
# for t in range(1, 25):
|
|
||||||
# states = set()
|
|
||||||
# for state in state_after_t[t - 1]:
|
|
||||||
# robots_that_can_be_built = [
|
|
||||||
# robot
|
|
||||||
# for robot in REAGENTS
|
|
||||||
# if all(
|
|
||||||
# state.reagents[reagent] >= blueprint[robot].get(reagent, 0)
|
|
||||||
# for reagent in REAGENTS
|
|
||||||
# )
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# new_states = set()
|
|
||||||
|
|
||||||
# # new reagents
|
|
||||||
# reagents = {
|
|
||||||
# reagent: state.reagents[reagent] + state.robots[reagent]
|
|
||||||
# for reagent in REAGENTS
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # if we can build anything, there is no point in waiting
|
|
||||||
# if len(robots_that_can_be_built) != len(REAGENTS):
|
|
||||||
# new_states.add(State(robots=state.robots, reagents=reagents))
|
|
||||||
|
|
||||||
# for robot in robots_that_can_be_built:
|
|
||||||
# robots = state.robots.copy()
|
|
||||||
# robots[robot] += 1
|
|
||||||
# reagents = {
|
|
||||||
# reagent: state.reagents[reagent]
|
|
||||||
# + state.robots[reagent]
|
|
||||||
# - blueprint[robot].get(reagent, 0)
|
|
||||||
# for reagent in REAGENTS
|
|
||||||
# }
|
|
||||||
# new_states.add(State(robots=robots, reagents=reagents))
|
|
||||||
|
|
||||||
# new_states = [
|
|
||||||
# s1
|
|
||||||
# for s1 in new_states
|
|
||||||
# if not any(s1 is not s2 and dominates(s2, s1) for s2 in new_states)
|
|
||||||
# ]
|
|
||||||
|
|
||||||
# states = {
|
|
||||||
# s1 for s1 in states if not any(dominates(s2, s1) for s2 in new_states)
|
|
||||||
# }
|
|
||||||
# states.update(new_states)
|
|
||||||
|
|
||||||
# state_after_t[t] = states
|
|
||||||
|
|
||||||
# exit()
|
|
||||||
|
|
||||||
|
|
||||||
MAX_TIME = 24
|
def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int:
|
||||||
blueprint = blueprints[0]
|
|
||||||
|
|
||||||
state_after_t: dict[int, list[State]] = {0: [State()]}
|
# since we can only build one robot per time, we do not need more than X robots
|
||||||
|
# of type K where X is the maximum number of K required among all robots, e.g.,
|
||||||
|
# in the first toy blueprint, we need at most 4 ore robots, 14 clay ones and 7
|
||||||
|
# obsidian ones
|
||||||
|
maximums = {
|
||||||
|
name: max(blueprint[r].get(name, 0) for r in REAGENTS) for name in REAGENTS
|
||||||
|
}
|
||||||
|
|
||||||
for t in range(1, 25):
|
state_after_t: dict[int, set[State]] = {0: [State()]}
|
||||||
print(t, len(state_after_t[t - 1]))
|
|
||||||
|
|
||||||
bests_for_robots: dict[tuple[int, ...], list[State]] = {}
|
for t in range(1, max_time + 1):
|
||||||
bests_for_reagents: dict[tuple[int, ...], list[State]] = {}
|
|
||||||
|
|
||||||
state_after_t[t] = []
|
# list of new states at the end of step t that we are going to prune later
|
||||||
|
states_for_t: set[State] = set()
|
||||||
|
|
||||||
t1 = time.time()
|
for state in state_after_t[t - 1]:
|
||||||
|
robots_that_can_be_built = [
|
||||||
|
robot
|
||||||
|
for robot in REAGENTS
|
||||||
|
if all(
|
||||||
|
state.reagents[reagent] >= blueprint[robot].get(reagent, 0)
|
||||||
|
for reagent in REAGENTS
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
for state in state_after_t[t - 1]:
|
states_for_t.add(
|
||||||
robots_that_can_be_built = [
|
State(
|
||||||
robot
|
robots=state.robots,
|
||||||
for robot in REAGENTS
|
reagents={
|
||||||
if all(
|
reagent: state.reagents[reagent] + state.robots[reagent]
|
||||||
state.reagents[reagent] >= blueprint[robot].get(reagent, 0)
|
for reagent in REAGENTS
|
||||||
for reagent in REAGENTS
|
},
|
||||||
|
)
|
||||||
)
|
)
|
||||||
]
|
|
||||||
|
|
||||||
# print(t, robots_that_can_be_built)
|
if "geode" in robots_that_can_be_built:
|
||||||
new_states: set[State] = set()
|
robots_that_can_be_built = ["geode"]
|
||||||
|
else:
|
||||||
|
robots_that_can_be_built = [
|
||||||
|
robot
|
||||||
|
for robot in robots_that_can_be_built
|
||||||
|
if state.robots[robot] < maximums[robot]
|
||||||
|
]
|
||||||
|
|
||||||
# new reagents
|
for robot in robots_that_can_be_built:
|
||||||
reagents = {
|
robots = state.robots.copy()
|
||||||
reagent: state.reagents[reagent] + state.robots[reagent]
|
robots[robot] += 1
|
||||||
for reagent in REAGENTS
|
reagents = {
|
||||||
|
reagent: state.reagents[reagent]
|
||||||
|
+ state.robots[reagent]
|
||||||
|
- blueprint[robot].get(reagent, 0)
|
||||||
|
for reagent in REAGENTS
|
||||||
|
}
|
||||||
|
states_for_t.add(State(robots=robots, reagents=reagents))
|
||||||
|
|
||||||
|
# use numpy to switch computation of dominated states -> store each state
|
||||||
|
# as a 8 array and use numpy broadcasting to find dominated states
|
||||||
|
states_after = np.asarray(list(states_for_t))
|
||||||
|
np_states = np.array(
|
||||||
|
[
|
||||||
|
[state.robots[r] for r in REAGENTS]
|
||||||
|
+ [state.reagents[r] for r in REAGENTS]
|
||||||
|
for state in states_after
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
to_keep = []
|
||||||
|
while len(np_states) > 0:
|
||||||
|
first_dom = (np_states[1:] >= np_states[0]).all(axis=1).any()
|
||||||
|
|
||||||
|
if first_dom:
|
||||||
|
np_states = np_states[1:]
|
||||||
|
else:
|
||||||
|
to_keep.append(np_states[0])
|
||||||
|
np_states = np_states[1:][~(np_states[1:] <= np_states[0]).all(axis=1)]
|
||||||
|
|
||||||
|
state_after_t[t] = {
|
||||||
|
State(
|
||||||
|
robots=dict(zip(REAGENTS, row[:4])),
|
||||||
|
reagents=dict(zip(REAGENTS, row[4:])),
|
||||||
|
)
|
||||||
|
for row in to_keep
|
||||||
}
|
}
|
||||||
|
|
||||||
# if we can build anything, there is no point in waiting
|
return max(state.reagents["geode"] for state in state_after_t[max_time])
|
||||||
new_states.add(State(robots=state.robots, reagents=reagents))
|
|
||||||
|
|
||||||
for robot in robots_that_can_be_built:
|
|
||||||
robots = state.robots.copy()
|
|
||||||
robots[robot] += 1
|
|
||||||
reagents = {
|
|
||||||
reagent: state.reagents[reagent]
|
|
||||||
+ state.robots[reagent]
|
|
||||||
- blueprint[robot].get(reagent, 0)
|
|
||||||
for reagent in REAGENTS
|
|
||||||
}
|
|
||||||
new_states.add(State(robots=robots, reagents=reagents))
|
|
||||||
|
|
||||||
for s1 in new_states:
|
answer_1 = sum(
|
||||||
r1 = tuple(s1.robots[r] for r in REAGENTS)
|
(i_blueprint + 1) * run(blueprint, 24)
|
||||||
if r1 not in bests_for_robots:
|
for i_blueprint, blueprint in enumerate(blueprints)
|
||||||
bests_for_robots[r1] = [s1]
|
)
|
||||||
else:
|
print(f"answer 1 is {answer_1}")
|
||||||
is_dominated = False
|
|
||||||
for s2 in bests_for_robots[r1]:
|
|
||||||
if all(s2.reagents[r] >= s1.reagents[r] for r in REAGENTS):
|
|
||||||
is_dominated = True
|
|
||||||
break
|
|
||||||
if not is_dominated:
|
|
||||||
bests_for_robots[r1].append(s1)
|
|
||||||
|
|
||||||
r2 = tuple(s1.reagents[r] for r in REAGENTS)
|
answer_2 = run(blueprints[0], 32) * run(blueprints[1], 32) * run(blueprints[2], 32)
|
||||||
if r2 not in bests_for_reagents:
|
print(f"answer 2 is {answer_2}")
|
||||||
bests_for_reagents[r2] = [s1]
|
|
||||||
else:
|
|
||||||
is_dominated = False
|
|
||||||
for s2 in bests_for_reagents[r2]:
|
|
||||||
if all(s2.robots[r] >= s1.robots[r] for r in REAGENTS):
|
|
||||||
is_dominated = True
|
|
||||||
break
|
|
||||||
if not is_dominated:
|
|
||||||
bests_for_reagents[r2].append(s1)
|
|
||||||
# state_after_t[t].extend(new_states)
|
|
||||||
|
|
||||||
t2 = time.time()
|
|
||||||
|
|
||||||
for bests in bests_for_robots.values():
|
|
||||||
dominated = [False for _ in range(len(bests))]
|
|
||||||
for i_s1, s1 in enumerate(bests):
|
|
||||||
if dominated[i_s1]:
|
|
||||||
continue
|
|
||||||
for i_s2, s2 in enumerate(bests[i_s1 + 1 :], start=i_s1 + 1):
|
|
||||||
if dominated[i_s2]:
|
|
||||||
continue
|
|
||||||
if all(s1.reagents[r] >= s2.reagents[r] for r in REAGENTS):
|
|
||||||
dominated[i_s2] = True
|
|
||||||
state_after_t[t].extend(
|
|
||||||
s1 for i_s1, s1 in enumerate(bests) if not dominated[i_s1]
|
|
||||||
)
|
|
||||||
for bests in bests_for_reagents.values():
|
|
||||||
dominated = [False for _ in range(len(bests))]
|
|
||||||
for i_s1, s1 in enumerate(bests):
|
|
||||||
if dominated[i_s1]:
|
|
||||||
continue
|
|
||||||
for i_s2, s2 in enumerate(bests[i_s1 + 1 :], start=i_s1 + 1):
|
|
||||||
if dominated[i_s2]:
|
|
||||||
continue
|
|
||||||
if all(s1.robots[r] >= s2.robots[r] for r in REAGENTS):
|
|
||||||
dominated[i_s2] = True
|
|
||||||
state_after_t[t].extend(
|
|
||||||
s1 for i_s1, s1 in enumerate(bests) if not dominated[i_s1]
|
|
||||||
)
|
|
||||||
|
|
||||||
t3 = time.time()
|
|
||||||
|
|
||||||
np_states = np.array(
|
|
||||||
[
|
|
||||||
[state.robots[r] for r in REAGENTS] + [state.reagents[r] for r in REAGENTS]
|
|
||||||
for state in state_after_t[t]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
dominated = np.zeros(len(np_states), dtype=bool)
|
|
||||||
|
|
||||||
t4 = time.time()
|
|
||||||
|
|
||||||
# c = (np_states[None, :, :] <= np_states[:, None, :]).all(axis=-1)
|
|
||||||
# c[np.arange(len(np_states)), np.arange(len(np_states))] = False
|
|
||||||
# dominated = c.any(axis=0)
|
|
||||||
|
|
||||||
for i in range(len(np_states)):
|
|
||||||
if dominated[i]:
|
|
||||||
continue
|
|
||||||
dominated[i] = not (np_states[i + 1 :] <= np_states[i]).any(axis=1)
|
|
||||||
|
|
||||||
dominated[i + 1 :] = (np_states[i + 1 :] <= np_states[i]).all(axis=1)
|
|
||||||
|
|
||||||
t5 = time.time()
|
|
||||||
|
|
||||||
state_after_t[t] = list(np.array(state_after_t[t])[~dominated])
|
|
||||||
|
|
||||||
t6 = time.time()
|
|
||||||
|
|
||||||
print(
|
|
||||||
"->",
|
|
||||||
t,
|
|
||||||
len(state_after_t[t]),
|
|
||||||
dominated.sum(),
|
|
||||||
t2 - t1,
|
|
||||||
t3 - t2,
|
|
||||||
t4 - t3,
|
|
||||||
t5 - t4,
|
|
||||||
t6 - t5,
|
|
||||||
)
|
|
||||||
|
|
||||||
# print("->", len(state_after_t[t]))
|
|
||||||
|
|
||||||
# dominated = [False for _ in range(len(state_after_t[t]))]
|
|
||||||
# keep = set()
|
|
||||||
# for i_s1, s1 in enumerate(tqdm(state_after_t[t])):
|
|
||||||
# if dominated[i_s1]:
|
|
||||||
# continue
|
|
||||||
# for i_s2, s2 in enumerate(state_after_t[t][i_s1 + 1 :], start=i_s1 + 1):
|
|
||||||
# if dominated[i_s2]:
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# if dominates(s1, s2):
|
|
||||||
# dominated[i_s2] = True
|
|
||||||
# elif dominates(s2, s1):
|
|
||||||
# dominated[i_s1] = True
|
|
||||||
# break
|
|
||||||
|
|
||||||
# if not dominated[i_s1]:
|
|
||||||
# keep.add(s1)
|
|
||||||
|
|
||||||
# state_after_t[t] = list(keep)
|
|
||||||
|
|
||||||
# print(len(state_after_t[t]))
|
|
||||||
# print(sum(dominated))
|
|
||||||
# break
|
|
||||||
|
|
||||||
print(max(state.reagents["geode"] for state in state_after_t[24]))
|
|
||||||
|
77
2022/day20.py
Normal file
77
2022/day20.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class Number:
|
||||||
|
current: int
|
||||||
|
value: int
|
||||||
|
|
||||||
|
def __init__(self, value: int):
|
||||||
|
self.current = 0
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.value)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt(numbers: list[Number], key: int, rounds: int) -> int:
|
||||||
|
|
||||||
|
numbers = numbers.copy()
|
||||||
|
original = numbers.copy()
|
||||||
|
|
||||||
|
for index, number in enumerate(numbers):
|
||||||
|
number.current = index
|
||||||
|
|
||||||
|
for _ in range(rounds):
|
||||||
|
for number in original:
|
||||||
|
index = number.current
|
||||||
|
offset = (number.value * key) % (len(numbers) - 1)
|
||||||
|
target = index + offset
|
||||||
|
|
||||||
|
# need to wrap
|
||||||
|
if target >= len(numbers):
|
||||||
|
target = offset - (len(numbers) - index) + 1
|
||||||
|
|
||||||
|
for number_2 in numbers[target:index]:
|
||||||
|
number_2.current += 1
|
||||||
|
|
||||||
|
numbers = (
|
||||||
|
numbers[:target]
|
||||||
|
+ [number]
|
||||||
|
+ numbers[target:index]
|
||||||
|
+ numbers[index + 1 :]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for number_2 in numbers[index : target + 1]:
|
||||||
|
number_2.current -= 1
|
||||||
|
|
||||||
|
numbers = (
|
||||||
|
numbers[:index]
|
||||||
|
+ numbers[index + 1 : target + 1]
|
||||||
|
+ [number]
|
||||||
|
+ numbers[target + 1 :]
|
||||||
|
)
|
||||||
|
number.current = target
|
||||||
|
|
||||||
|
index_of_0 = next(
|
||||||
|
filter(lambda index: numbers[index].value == 0, range(len(numbers)))
|
||||||
|
)
|
||||||
|
return sum(
|
||||||
|
numbers[(index_of_0 + offset) % len(numbers)].value * key
|
||||||
|
for offset in (1000, 2000, 3000)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
numbers = [Number(int(x)) for i, x in enumerate(sys.stdin.readlines())]
|
||||||
|
|
||||||
|
answer_1 = decrypt(numbers, 1, 1)
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
answer_2 = decrypt(numbers, 811589153, 10)
|
||||||
|
print(f"answer 2 is {answer_2}")
|
109
2022/day21.py
Normal file
109
2022/day21.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
import operator
|
||||||
|
import sys
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
|
def compute(monkeys: dict[str, int | tuple[str, str, str]], monkey: str) -> int:
|
||||||
|
value = monkeys[monkey]
|
||||||
|
if isinstance(value, int):
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
op: dict[str, Callable[[int, int], int]] = {
|
||||||
|
"+": operator.add,
|
||||||
|
"-": operator.sub,
|
||||||
|
"*": operator.mul,
|
||||||
|
"/": operator.floordiv,
|
||||||
|
}
|
||||||
|
value = op[value[1]](compute(monkeys, value[0]), compute(monkeys, value[2]))
|
||||||
|
monkeys[monkey] = value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def invert(
|
||||||
|
monkeys: dict[str, int | tuple[str, str, str]], monkey: str, target: int
|
||||||
|
) -> dict[str, int | tuple[str, str, str]]:
|
||||||
|
"""
|
||||||
|
Revert the given mapping from monkey name to value or operation such that
|
||||||
|
the value from 'monkey' is computable by inverting operation until the root is
|
||||||
|
found.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
monkeys: Dictionary of monkeys, that will be updated and returned.
|
||||||
|
monkey: Name of the monkey to start from.
|
||||||
|
target: Target value to set for the monkey that depends on root.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The given dictionary of monkeys.
|
||||||
|
"""
|
||||||
|
|
||||||
|
monkeys = monkeys.copy()
|
||||||
|
|
||||||
|
depends: dict[str, str] = {}
|
||||||
|
for m, v in monkeys.items():
|
||||||
|
if isinstance(v, int):
|
||||||
|
continue
|
||||||
|
|
||||||
|
op1, _, op2 = v
|
||||||
|
|
||||||
|
assert op1 not in depends
|
||||||
|
assert op2 not in depends
|
||||||
|
depends[op1] = m
|
||||||
|
depends[op2] = m
|
||||||
|
|
||||||
|
invert_op = {"+": "-", "-": "+", "*": "/", "/": "*"}
|
||||||
|
|
||||||
|
current = monkey
|
||||||
|
while True:
|
||||||
|
dep = depends[current]
|
||||||
|
|
||||||
|
if dep == "root":
|
||||||
|
monkeys[current] = target
|
||||||
|
break
|
||||||
|
|
||||||
|
val = monkeys[dep]
|
||||||
|
assert not isinstance(val, int)
|
||||||
|
|
||||||
|
op1, ope, op2 = val
|
||||||
|
|
||||||
|
if op1 == current:
|
||||||
|
monkeys[current] = (dep, invert_op[ope], op2)
|
||||||
|
elif ope in ("+", "*"):
|
||||||
|
monkeys[current] = (dep, invert_op[ope], op1)
|
||||||
|
else:
|
||||||
|
monkeys[current] = (op1, ope, dep)
|
||||||
|
|
||||||
|
current = dep
|
||||||
|
|
||||||
|
return monkeys
|
||||||
|
|
||||||
|
|
||||||
|
lines = sys.stdin.read().splitlines()
|
||||||
|
|
||||||
|
monkeys: dict[str, int | tuple[str, str, str]] = {}
|
||||||
|
|
||||||
|
op_monkeys: set[str] = set()
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
parts = line.split(":")
|
||||||
|
name = parts[0].strip()
|
||||||
|
|
||||||
|
try:
|
||||||
|
value = int(parts[1].strip())
|
||||||
|
monkeys[name] = value
|
||||||
|
except ValueError:
|
||||||
|
op1, ope, op2 = parts[1].strip().split()
|
||||||
|
monkeys[name] = (op1, ope, op2)
|
||||||
|
|
||||||
|
op_monkeys.add(name)
|
||||||
|
|
||||||
|
|
||||||
|
answer_1 = compute(monkeys.copy(), "root")
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
# assume the second operand of 'root' can be computed, and the first one depends on
|
||||||
|
# humn, which is the case is my input and the test input
|
||||||
|
p1, _, p2 = monkeys["root"] # type: ignore
|
||||||
|
answer_2 = compute(invert(monkeys, "humn", compute(monkeys.copy(), p2)), "humn")
|
||||||
|
print(f"answer 2 is {answer_2}")
|
225
2022/day22.py
Normal file
225
2022/day22.py
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
VOID, EMPTY, WALL = 0, 1, 2
|
||||||
|
TILE_FROM_CHAR = {" ": VOID, ".": EMPTY, "#": WALL}
|
||||||
|
|
||||||
|
SCORES = {"E": 0, "S": 1, "W": 2, "N": 3}
|
||||||
|
|
||||||
|
|
||||||
|
board_map_s, direction_s = sys.stdin.read().split("\n\n")
|
||||||
|
|
||||||
|
# board
|
||||||
|
board_lines = board_map_s.splitlines()
|
||||||
|
max_line = max(len(line) for line in board_lines)
|
||||||
|
board = np.array(
|
||||||
|
[
|
||||||
|
[TILE_FROM_CHAR[c] for c in row] + [VOID] * (max_line - len(row))
|
||||||
|
for row in board_map_s.splitlines()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
directions = [
|
||||||
|
int(p1) if p2 else p1 for p1, p2 in re.findall(R"(([0-9])+|L|R)", direction_s)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# find on each row and column the first and last non-void
|
||||||
|
row_first_non_void = np.argmax(board != VOID, axis=1)
|
||||||
|
row_last_non_void = board.shape[1] - np.argmax(board[:, ::-1] != VOID, axis=1) - 1
|
||||||
|
col_first_non_void = np.argmax(board != VOID, axis=0)
|
||||||
|
col_last_non_void = board.shape[0] - np.argmax(board[::-1, :] != VOID, axis=0) - 1
|
||||||
|
|
||||||
|
|
||||||
|
faces = np.zeros_like(board)
|
||||||
|
size = np.gcd(board.shape[0], board.shape[1])
|
||||||
|
for row in range(0, board.shape[0], size):
|
||||||
|
for col in range(row_first_non_void[row], row_last_non_void[row], size):
|
||||||
|
faces[row : row + size, col : col + size] = faces.max() + 1
|
||||||
|
|
||||||
|
SIZE = np.gcd(*board.shape)
|
||||||
|
|
||||||
|
# TODO: deduce this from the actual cube...
|
||||||
|
faces_wrap: dict[int, dict[str, Callable[[int, int], tuple[int, int, str]]]]
|
||||||
|
if board.shape == (12, 16): # example
|
||||||
|
faces_wrap = {
|
||||||
|
1: {
|
||||||
|
"W": lambda y, x: (4, 4 + y, "S"), # 3N
|
||||||
|
"N": lambda y, x: (4, 11 - x, "S"), # 2N
|
||||||
|
"E": lambda y, x: (11 - y, 15, "W"), # 6E
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"W": lambda y, x: (11, 19 - y, "N"), # 6S
|
||||||
|
"N": lambda y, x: (0, 11 - y, "S"), # 1N
|
||||||
|
"S": lambda y, x: (11, 11 - x, "N"), # 5S
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"N": lambda y, x: (x - 4, 8, "E"), # 1W
|
||||||
|
"S": lambda y, x: (15 - x, 8, "E"), # 5W
|
||||||
|
},
|
||||||
|
4: {"E": lambda y, x: (8, 19 - y, "S")}, # 6N
|
||||||
|
5: {
|
||||||
|
"W": lambda y, x: (7, 15 - y, "N"), # 3S
|
||||||
|
"S": lambda y, x: (7, 11 - x, "N"), # 2S
|
||||||
|
},
|
||||||
|
6: {
|
||||||
|
"N": lambda y, x: (19 - x, 11, "W"), # 4E
|
||||||
|
"E": lambda y, x: (11 - y, 11, "W"), # 1E
|
||||||
|
"S": lambda y, x: (19 - x, 0, "E"), # 2W
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
faces_wrap = {
|
||||||
|
1: {
|
||||||
|
"W": lambda y, x: (3 * SIZE - y - 1, 0, "E"), # 4W
|
||||||
|
"N": lambda y, x: (2 * SIZE + x, 0, "E"), # 6W
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"N": lambda y, x: (4 * SIZE - 1, x - 2 * SIZE, "N"), # 6S
|
||||||
|
"E": lambda y, x: (3 * SIZE - y - 1, 2 * SIZE - 1, "W"), # 5E
|
||||||
|
"S": lambda y, x: (x - SIZE, 2 * SIZE - 1, "W"), # 3E
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"W": lambda y, x: (2 * SIZE, y - SIZE, "S"), # 4N
|
||||||
|
"E": lambda y, x: (SIZE - 1, SIZE + y, "N"), # 2S
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
"W": lambda y, x: (3 * SIZE - y - 1, SIZE, "E"), # 1W
|
||||||
|
"N": lambda y, x: (SIZE + x, SIZE, "E"), # 3W
|
||||||
|
},
|
||||||
|
5: {
|
||||||
|
"E": lambda y, x: (3 * SIZE - y - 1, 3 * SIZE - 1, "W"), # 2E
|
||||||
|
"S": lambda y, x: (2 * SIZE + x, SIZE - 1, "W"), # 6E
|
||||||
|
},
|
||||||
|
6: {
|
||||||
|
"W": lambda y, x: (0, y - 2 * SIZE, "S"), # 1N
|
||||||
|
"E": lambda y, x: (3 * SIZE - 1, y - 2 * SIZE, "N"), # 5S
|
||||||
|
"S": lambda y, x: (0, x + 2 * SIZE, "S"), # 2N
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_part_1(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||||
|
if r0 == "E":
|
||||||
|
return y0, row_first_non_void[y0], r0
|
||||||
|
elif r0 == "S":
|
||||||
|
return col_first_non_void[x0], x0, r0
|
||||||
|
elif r0 == "W":
|
||||||
|
return y0, row_last_non_void[y0], r0
|
||||||
|
elif r0 == "N":
|
||||||
|
return col_last_non_void[x0], x0, r0
|
||||||
|
|
||||||
|
assert False
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_part_2(y0: int, x0: int, r0: str) -> tuple[int, int, str]:
|
||||||
|
cube = faces[y0, x0]
|
||||||
|
assert r0 in faces_wrap[cube]
|
||||||
|
return faces_wrap[cube][r0](y0, x0)
|
||||||
|
|
||||||
|
|
||||||
|
def run(wrap: Callable[[int, int, str], tuple[int, int, str]]) -> tuple[int, int, str]:
|
||||||
|
|
||||||
|
y0 = 0
|
||||||
|
x0 = np.where(board[0] == EMPTY)[0][0]
|
||||||
|
r0 = "E"
|
||||||
|
|
||||||
|
for direction in directions:
|
||||||
|
if isinstance(direction, int):
|
||||||
|
while direction > 0:
|
||||||
|
if r0 == "E":
|
||||||
|
xi = np.where(board[y0, x0 + 1 : x0 + direction + 1] == WALL)[0]
|
||||||
|
if len(xi):
|
||||||
|
x0 = x0 + xi[0]
|
||||||
|
direction = 0
|
||||||
|
elif (
|
||||||
|
x0 + direction < board.shape[1]
|
||||||
|
and board[y0, x0 + direction] == EMPTY
|
||||||
|
):
|
||||||
|
x0 = x0 + direction
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
|
if board[y0_t, x0_t] == WALL:
|
||||||
|
x0 = row_last_non_void[y0]
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
direction = direction - (row_last_non_void[y0] - x0) - 1
|
||||||
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
|
elif r0 == "S":
|
||||||
|
yi = np.where(board[y0 + 1 : y0 + direction + 1, x0] == WALL)[0]
|
||||||
|
if len(yi):
|
||||||
|
y0 = y0 + yi[0]
|
||||||
|
direction = 0
|
||||||
|
elif (
|
||||||
|
y0 + direction < board.shape[0]
|
||||||
|
and board[y0 + direction, x0] == EMPTY
|
||||||
|
):
|
||||||
|
y0 = y0 + direction
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
|
if board[y0_t, x0_t] == WALL:
|
||||||
|
y0 = col_last_non_void[x0]
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
direction = direction - (col_last_non_void[x0] - y0) - 1
|
||||||
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
|
elif r0 == "W":
|
||||||
|
left = max(x0 - direction - 1, 0)
|
||||||
|
xi = np.where(board[y0, left:x0] == WALL)[0]
|
||||||
|
if len(xi):
|
||||||
|
x0 = left + xi[-1] + 1
|
||||||
|
direction = 0
|
||||||
|
elif x0 - direction >= 0 and board[y0, x0 - direction] == EMPTY:
|
||||||
|
x0 = x0 - direction
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
|
if board[y0_t, x0_t] == WALL:
|
||||||
|
x0 = row_first_non_void[y0]
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
direction = direction - (x0 - row_first_non_void[y0]) - 1
|
||||||
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
|
elif r0 == "N":
|
||||||
|
top = max(y0 - direction - 1, 0)
|
||||||
|
yi = np.where(board[top:y0, x0] == WALL)[0]
|
||||||
|
if len(yi):
|
||||||
|
y0 = top + yi[-1] + 1
|
||||||
|
direction = 0
|
||||||
|
elif y0 - direction >= 0 and board[y0 - direction, x0] == EMPTY:
|
||||||
|
y0 = y0 - direction
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
y0_t, x0_t, r0_t = wrap(y0, x0, r0)
|
||||||
|
if board[y0_t, x0_t] == WALL:
|
||||||
|
y0 = col_first_non_void[x0]
|
||||||
|
direction = 0
|
||||||
|
else:
|
||||||
|
direction = direction - (y0 - col_first_non_void[x0]) - 1
|
||||||
|
y0, x0, r0 = y0_t, x0_t, r0_t
|
||||||
|
else:
|
||||||
|
r0 = {
|
||||||
|
"E": {"L": "N", "R": "S"},
|
||||||
|
"N": {"L": "W", "R": "E"},
|
||||||
|
"W": {"L": "S", "R": "N"},
|
||||||
|
"S": {"L": "E", "R": "W"},
|
||||||
|
}[r0][direction]
|
||||||
|
|
||||||
|
return y0, x0, r0
|
||||||
|
|
||||||
|
|
||||||
|
y1, x1, r1 = run(wrap_part_1)
|
||||||
|
answer_1 = 1000 * (1 + y1) + 4 * (1 + x1) + SCORES[r1]
|
||||||
|
print(f"answer 1 is {answer_1}")
|
||||||
|
|
||||||
|
y2, x2, r2 = run(wrap_part_2)
|
||||||
|
answer_2 = 1000 * (1 + y2) + 4 * (1 + x2) + SCORES[r2]
|
||||||
|
print(f"answer 2 is {answer_2}")
|
3
2022/day23.py
Normal file
3
2022/day23.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
3
2022/day24.py
Normal file
3
2022/day24.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
3
2022/day25.py
Normal file
3
2022/day25.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
30
2022/inputs/day19.txt
Normal file
30
2022/inputs/day19.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 12 clay. Each geode robot costs 4 ore and 19 obsidian.
|
||||||
|
Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 7 obsidian.
|
||||||
|
Blueprint 3: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 3 ore and 12 obsidian.
|
||||||
|
Blueprint 4: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian.
|
||||||
|
Blueprint 5: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 13 obsidian.
|
||||||
|
Blueprint 6: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 7 clay. Each geode robot costs 4 ore and 11 obsidian.
|
||||||
|
Blueprint 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 17 obsidian.
|
||||||
|
Blueprint 8: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 13 clay. Each geode robot costs 3 ore and 7 obsidian.
|
||||||
|
Blueprint 9: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 3 ore and 15 obsidian.
|
||||||
|
Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 11 obsidian.
|
||||||
|
Blueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 2 ore and 15 obsidian.
|
||||||
|
Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 3 ore and 7 obsidian.
|
||||||
|
Blueprint 13: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 10 clay. Each geode robot costs 2 ore and 10 obsidian.
|
||||||
|
Blueprint 14: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 2 ore and 20 obsidian.
|
||||||
|
Blueprint 15: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 3 ore and 8 obsidian.
|
||||||
|
Blueprint 16: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 18 obsidian.
|
||||||
|
Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 9 clay. Each geode robot costs 3 ore and 19 obsidian.
|
||||||
|
Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 4 ore and 8 obsidian.
|
||||||
|
Blueprint 19: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 12 clay. Each geode robot costs 3 ore and 17 obsidian.
|
||||||
|
Blueprint 20: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 17 obsidian.
|
||||||
|
Blueprint 21: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 16 obsidian.
|
||||||
|
Blueprint 22: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 4 ore and 16 obsidian.
|
||||||
|
Blueprint 23: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 4 ore and 11 obsidian.
|
||||||
|
Blueprint 24: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 9 obsidian.
|
||||||
|
Blueprint 25: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian.
|
||||||
|
Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 4 ore and 7 obsidian.
|
||||||
|
Blueprint 27: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 8 clay. Each geode robot costs 2 ore and 14 obsidian.
|
||||||
|
Blueprint 28: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 3 ore and 14 obsidian.
|
||||||
|
Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 4 ore and 8 obsidian.
|
||||||
|
Blueprint 30: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 13 obsidian.
|
5000
2022/inputs/day20.txt
Normal file
5000
2022/inputs/day20.txt
Normal file
File diff suppressed because it is too large
Load Diff
1835
2022/inputs/day21.txt
Normal file
1835
2022/inputs/day21.txt
Normal file
File diff suppressed because it is too large
Load Diff
202
2022/inputs/day22.txt
Normal file
202
2022/inputs/day22.txt
Normal file
File diff suppressed because one or more lines are too long
0
2022/inputs/day23.txt
Normal file
0
2022/inputs/day23.txt
Normal file
0
2022/inputs/day24.txt
Normal file
0
2022/inputs/day24.txt
Normal file
0
2022/inputs/day25.txt
Normal file
0
2022/inputs/day25.txt
Normal file
14
2022/tests/day1.txt
Normal file
14
2022/tests/day1.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
1000
|
||||||
|
2000
|
||||||
|
3000
|
||||||
|
|
||||||
|
4000
|
||||||
|
|
||||||
|
5000
|
||||||
|
6000
|
||||||
|
|
||||||
|
7000
|
||||||
|
8000
|
||||||
|
9000
|
||||||
|
|
||||||
|
10000
|
146
2022/tests/day10.txt
Normal file
146
2022/tests/day10.txt
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
addx 15
|
||||||
|
addx -11
|
||||||
|
addx 6
|
||||||
|
addx -3
|
||||||
|
addx 5
|
||||||
|
addx -1
|
||||||
|
addx -8
|
||||||
|
addx 13
|
||||||
|
addx 4
|
||||||
|
noop
|
||||||
|
addx -1
|
||||||
|
addx 5
|
||||||
|
addx -1
|
||||||
|
addx 5
|
||||||
|
addx -1
|
||||||
|
addx 5
|
||||||
|
addx -1
|
||||||
|
addx 5
|
||||||
|
addx -1
|
||||||
|
addx -35
|
||||||
|
addx 1
|
||||||
|
addx 24
|
||||||
|
addx -19
|
||||||
|
addx 1
|
||||||
|
addx 16
|
||||||
|
addx -11
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 21
|
||||||
|
addx -15
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx -3
|
||||||
|
addx 9
|
||||||
|
addx 1
|
||||||
|
addx -3
|
||||||
|
addx 8
|
||||||
|
addx 1
|
||||||
|
addx 5
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx -36
|
||||||
|
noop
|
||||||
|
addx 1
|
||||||
|
addx 7
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 2
|
||||||
|
addx 6
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 7
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
addx -13
|
||||||
|
addx 13
|
||||||
|
addx 7
|
||||||
|
noop
|
||||||
|
addx 1
|
||||||
|
addx -33
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 2
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 8
|
||||||
|
noop
|
||||||
|
addx -1
|
||||||
|
addx 2
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
addx 17
|
||||||
|
addx -9
|
||||||
|
addx 1
|
||||||
|
addx 1
|
||||||
|
addx -3
|
||||||
|
addx 11
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx -13
|
||||||
|
addx -19
|
||||||
|
addx 1
|
||||||
|
addx 3
|
||||||
|
addx 26
|
||||||
|
addx -30
|
||||||
|
addx 12
|
||||||
|
addx -1
|
||||||
|
addx 3
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx -9
|
||||||
|
addx 18
|
||||||
|
addx 1
|
||||||
|
addx 2
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 9
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx -1
|
||||||
|
addx 2
|
||||||
|
addx -37
|
||||||
|
addx 1
|
||||||
|
addx 3
|
||||||
|
noop
|
||||||
|
addx 15
|
||||||
|
addx -21
|
||||||
|
addx 22
|
||||||
|
addx -6
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
addx 2
|
||||||
|
addx 1
|
||||||
|
noop
|
||||||
|
addx -10
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
addx 20
|
||||||
|
addx 1
|
||||||
|
addx 2
|
||||||
|
addx 2
|
||||||
|
addx -6
|
||||||
|
addx -11
|
||||||
|
noop
|
||||||
|
noop
|
||||||
|
noop
|
27
2022/tests/day11.txt
Normal file
27
2022/tests/day11.txt
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Monkey 0:
|
||||||
|
Starting items: 79, 98
|
||||||
|
Operation: new = old * 19
|
||||||
|
Test: divisible by 23
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 1:
|
||||||
|
Starting items: 54, 65, 75, 74
|
||||||
|
Operation: new = old + 6
|
||||||
|
Test: divisible by 19
|
||||||
|
If true: throw to monkey 2
|
||||||
|
If false: throw to monkey 0
|
||||||
|
|
||||||
|
Monkey 2:
|
||||||
|
Starting items: 79, 60, 97
|
||||||
|
Operation: new = old * old
|
||||||
|
Test: divisible by 13
|
||||||
|
If true: throw to monkey 1
|
||||||
|
If false: throw to monkey 3
|
||||||
|
|
||||||
|
Monkey 3:
|
||||||
|
Starting items: 74
|
||||||
|
Operation: new = old + 3
|
||||||
|
Test: divisible by 17
|
||||||
|
If true: throw to monkey 0
|
||||||
|
If false: throw to monkey 1
|
5
2022/tests/day12.txt
Normal file
5
2022/tests/day12.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Sabqponm
|
||||||
|
abcryxxl
|
||||||
|
accszExk
|
||||||
|
acctuvwj
|
||||||
|
abdefghi
|
23
2022/tests/day13.txt
Normal file
23
2022/tests/day13.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[1,1,3,1,1]
|
||||||
|
[1,1,5,1,1]
|
||||||
|
|
||||||
|
[[1],[2,3,4]]
|
||||||
|
[[1],4]
|
||||||
|
|
||||||
|
[9]
|
||||||
|
[[8,7,6]]
|
||||||
|
|
||||||
|
[[4,4],4,4]
|
||||||
|
[[4,4],4,4,4]
|
||||||
|
|
||||||
|
[7,7,7,7]
|
||||||
|
[7,7,7]
|
||||||
|
|
||||||
|
[]
|
||||||
|
[3]
|
||||||
|
|
||||||
|
[[[]]]
|
||||||
|
[[]]
|
||||||
|
|
||||||
|
[1,[2,[3,[4,[5,6,7]]]],8,9]
|
||||||
|
[1,[2,[3,[4,[5,6,0]]]],8,9]
|
2
2022/tests/day14.txt
Normal file
2
2022/tests/day14.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
498,4 -> 498,6 -> 496,6
|
||||||
|
503,4 -> 502,4 -> 502,9 -> 494,9
|
14
2022/tests/day15.txt
Normal file
14
2022/tests/day15.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
|
||||||
|
Sensor at x=9, y=16: closest beacon is at x=10, y=16
|
||||||
|
Sensor at x=13, y=2: closest beacon is at x=15, y=3
|
||||||
|
Sensor at x=12, y=14: closest beacon is at x=10, y=16
|
||||||
|
Sensor at x=10, y=20: closest beacon is at x=10, y=16
|
||||||
|
Sensor at x=14, y=17: closest beacon is at x=10, y=16
|
||||||
|
Sensor at x=8, y=7: closest beacon is at x=2, y=10
|
||||||
|
Sensor at x=2, y=0: closest beacon is at x=2, y=10
|
||||||
|
Sensor at x=0, y=11: closest beacon is at x=2, y=10
|
||||||
|
Sensor at x=20, y=14: closest beacon is at x=25, y=17
|
||||||
|
Sensor at x=17, y=20: closest beacon is at x=21, y=22
|
||||||
|
Sensor at x=16, y=7: closest beacon is at x=15, y=3
|
||||||
|
Sensor at x=14, y=3: closest beacon is at x=15, y=3
|
||||||
|
Sensor at x=20, y=1: closest beacon is at x=15, y=3
|
10
2022/tests/day16.txt
Normal file
10
2022/tests/day16.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||||
|
Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||||
|
Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||||
|
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||||
|
Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||||
|
Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||||
|
Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||||
|
Valve HH has flow rate=22; tunnel leads to valve GG
|
||||||
|
Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||||
|
Valve JJ has flow rate=21; tunnel leads to valve II
|
3
2022/tests/day2.txt
Normal file
3
2022/tests/day2.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
A Y
|
||||||
|
B X
|
||||||
|
C Z
|
7
2022/tests/day20.txt
Normal file
7
2022/tests/day20.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
1
|
||||||
|
2
|
||||||
|
-3
|
||||||
|
3
|
||||||
|
-2
|
||||||
|
0
|
||||||
|
4
|
15
2022/tests/day21.txt
Normal file
15
2022/tests/day21.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
root: pppw + sjmn
|
||||||
|
dbpl: 5
|
||||||
|
cczh: sllz + lgvd
|
||||||
|
zczc: 2
|
||||||
|
ptdq: humn - dvpt
|
||||||
|
dvpt: 3
|
||||||
|
lfqf: 4
|
||||||
|
humn: 5
|
||||||
|
ljgn: 2
|
||||||
|
sjmn: drzm * dbpl
|
||||||
|
sllz: 4
|
||||||
|
pppw: cczh / lfqf
|
||||||
|
lgvd: ljgn * ptdq
|
||||||
|
drzm: hmdt - zczc
|
||||||
|
hmdt: 32
|
14
2022/tests/day22.txt
Normal file
14
2022/tests/day22.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
...#
|
||||||
|
.#..
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
...#.......#
|
||||||
|
........#...
|
||||||
|
..#....#....
|
||||||
|
..........#.
|
||||||
|
...#....
|
||||||
|
.....#..
|
||||||
|
.#......
|
||||||
|
......#.
|
||||||
|
|
||||||
|
10R5L5R10L4R5L5
|
0
2022/tests/day23.txt
Normal file
0
2022/tests/day23.txt
Normal file
0
2022/tests/day24.txt
Normal file
0
2022/tests/day24.txt
Normal file
0
2022/tests/day25.txt
Normal file
0
2022/tests/day25.txt
Normal file
6
2022/tests/day3.txt
Normal file
6
2022/tests/day3.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
vJrwpWtwJgWrhcsFMMfFFhFp
|
||||||
|
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||||
|
PmmdzqPrVvPwwTWBwg
|
||||||
|
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||||
|
ttgJtRGJQctTZtZT
|
||||||
|
CrZsJsPPZsGzwwsLwLmpwMDw
|
6
2022/tests/day4.txt
Normal file
6
2022/tests/day4.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
2-4,6-8
|
||||||
|
2-3,4-5
|
||||||
|
5-7,7-9
|
||||||
|
2-8,3-7
|
||||||
|
6-6,4-6
|
||||||
|
2-6,4-8
|
9
2022/tests/day5.txt
Normal file
9
2022/tests/day5.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[D]
|
||||||
|
[N] [C]
|
||||||
|
[Z] [M] [P]
|
||||||
|
1 2 3
|
||||||
|
|
||||||
|
move 1 from 2 to 1
|
||||||
|
move 3 from 1 to 3
|
||||||
|
move 2 from 2 to 1
|
||||||
|
move 1 from 1 to 2
|
1
2022/tests/day6.txt
Normal file
1
2022/tests/day6.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mjqjpqmgbljsphdztnvjfqwrcgsmlb
|
23
2022/tests/day7.txt
Normal file
23
2022/tests/day7.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
$ cd /
|
||||||
|
$ ls
|
||||||
|
dir a
|
||||||
|
14848514 b.txt
|
||||||
|
8504156 c.dat
|
||||||
|
dir d
|
||||||
|
$ cd a
|
||||||
|
$ ls
|
||||||
|
dir e
|
||||||
|
29116 f
|
||||||
|
2557 g
|
||||||
|
62596 h.lst
|
||||||
|
$ cd e
|
||||||
|
$ ls
|
||||||
|
584 i
|
||||||
|
$ cd ..
|
||||||
|
$ cd ..
|
||||||
|
$ cd d
|
||||||
|
$ ls
|
||||||
|
4060174 j
|
||||||
|
8033020 d.log
|
||||||
|
5626152 d.ext
|
||||||
|
7214296 k
|
5
2022/tests/day8.txt
Normal file
5
2022/tests/day8.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
30373
|
||||||
|
25512
|
||||||
|
65332
|
||||||
|
33549
|
||||||
|
35390
|
8
2022/tests/day9.txt
Normal file
8
2022/tests/day9.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
R 4
|
||||||
|
U 4
|
||||||
|
L 3
|
||||||
|
D 1
|
||||||
|
R 4
|
||||||
|
D 1
|
||||||
|
L 5
|
||||||
|
R 2
|
Reference in New Issue
Block a user