Solve 2018 day 21, 2020 day 12 and improve 2022 day 19
This commit is contained in:
52
2018/d21.py
Normal file
52
2018/d21.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
from lib import get_data, str_to_ints
|
||||||
|
import d16
|
||||||
|
|
||||||
|
|
||||||
|
def run(data, break_after=None, reg_zero_init=0):
|
||||||
|
ip = None
|
||||||
|
regs = [0 for _ in range(6)]
|
||||||
|
regs[0] = reg_zero_init
|
||||||
|
|
||||||
|
insts = []
|
||||||
|
for line in data.splitlines():
|
||||||
|
if line.startswith("#"):
|
||||||
|
(ip,) = str_to_ints(line)
|
||||||
|
else:
|
||||||
|
fs = line.split()
|
||||||
|
vals = str_to_ints(line)
|
||||||
|
insts.append([fs[0]] + vals)
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
assert ip is not None
|
||||||
|
seen = set()
|
||||||
|
last_added = None
|
||||||
|
while regs[ip] < len(insts):
|
||||||
|
if break_after is not None and count > break_after:
|
||||||
|
break
|
||||||
|
if regs[ip] == 28:
|
||||||
|
r4 = regs[4]
|
||||||
|
|
||||||
|
if len(seen) == 0:
|
||||||
|
print(r4)
|
||||||
|
|
||||||
|
if r4 in seen:
|
||||||
|
print(last_added)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
seen.add(r4)
|
||||||
|
last_added = r4
|
||||||
|
|
||||||
|
inst = insts[regs[ip]]
|
||||||
|
f = getattr(d16, inst[0])
|
||||||
|
f(regs, *inst[1:])
|
||||||
|
regs[ip] += 1
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data = get_data(__file__)
|
||||||
|
run(data, reg_zero_init=333)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
82
2020/d12.py
Normal file
82
2020/d12.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
from lib import get_data
|
||||||
|
|
||||||
|
DIRS = {
|
||||||
|
"N": (-1, 0),
|
||||||
|
"E": (0, 1),
|
||||||
|
"S": (1, 0),
|
||||||
|
"W": (0, -1),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def part_1(data):
|
||||||
|
dir_key = "E"
|
||||||
|
pos = 0, 0
|
||||||
|
dirs = "NESW"
|
||||||
|
|
||||||
|
for line in data.splitlines():
|
||||||
|
c = line[0]
|
||||||
|
v = int(line[1:])
|
||||||
|
if c in DIRS.keys():
|
||||||
|
pos = pos[0] + v * DIRS[c][0], pos[1] + v * DIRS[c][1]
|
||||||
|
elif c == "F":
|
||||||
|
dir = DIRS[dir_key]
|
||||||
|
pos = (pos[0] + v * dir[0], pos[1] + v * dir[1])
|
||||||
|
elif c == "R":
|
||||||
|
assert v % 90 == 0
|
||||||
|
dir_key = dirs[(dirs.index(dir_key) + v // 90) % len(dirs)]
|
||||||
|
elif c == "L":
|
||||||
|
assert v % 90 == 0
|
||||||
|
dir_key = dirs[(dirs.index(dir_key) - v // 90) % len(dirs)]
|
||||||
|
else:
|
||||||
|
print(c, v)
|
||||||
|
assert False
|
||||||
|
print(sum(map(abs, pos)))
|
||||||
|
|
||||||
|
|
||||||
|
def part_2(data):
|
||||||
|
way_point = (-1, 10)
|
||||||
|
pos = 0, 0
|
||||||
|
|
||||||
|
for line in data.splitlines():
|
||||||
|
c = line[0]
|
||||||
|
v = int(line[1:])
|
||||||
|
if c in DIRS.keys():
|
||||||
|
way_point = way_point[0] + v * DIRS[c][0], way_point[1] + v * DIRS[c][1]
|
||||||
|
elif c == "F":
|
||||||
|
pos = (pos[0] + v * way_point[0], pos[1] + v * way_point[1])
|
||||||
|
elif c == "R":
|
||||||
|
row, col = way_point
|
||||||
|
if v == 90:
|
||||||
|
way_point = (col, -row)
|
||||||
|
elif v == 180:
|
||||||
|
way_point = (-row, -col)
|
||||||
|
elif v == 270:
|
||||||
|
way_point = (-col, row)
|
||||||
|
else:
|
||||||
|
print(c, v)
|
||||||
|
assert False
|
||||||
|
elif c == "L":
|
||||||
|
row, col = way_point
|
||||||
|
if v == 90:
|
||||||
|
way_point = (-col, row)
|
||||||
|
elif v == 180:
|
||||||
|
way_point = (-row, -col)
|
||||||
|
elif v == 270:
|
||||||
|
way_point = (col, -row)
|
||||||
|
else:
|
||||||
|
print(c, v)
|
||||||
|
assert False
|
||||||
|
else:
|
||||||
|
print(c, v)
|
||||||
|
assert False
|
||||||
|
print(sum(map(abs, pos)))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data = get_data(__file__)
|
||||||
|
part_1(data)
|
||||||
|
part_2(data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
161
2022/d19.py
161
2022/d19.py
@@ -1,117 +1,66 @@
|
|||||||
from lib import *
|
import re
|
||||||
|
from lib import get_data, str_to_ints
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
EXAMPLE = """
|
data = get_data(__file__)
|
||||||
Blueprint 1:
|
|
||||||
Each ore robot costs 4 ore.
|
|
||||||
Each clay robot costs 2 ore.
|
|
||||||
Each obsidian robot costs 3 ore and 14 clay.
|
|
||||||
Each geode robot costs 2 ore and 7 obsidian.
|
|
||||||
|
|
||||||
Blueprint 2:
|
p1 = 0
|
||||||
Each ore robot costs 2 ore.
|
p2 = 1
|
||||||
Each clay robot costs 3 ore.
|
|
||||||
Each obsidian robot costs 3 ore and 8 clay.
|
|
||||||
Each geode robot costs 3 ore and 12 obsidian.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def solve(input: Input, second=False):
|
for line in data.splitlines():
|
||||||
if not second:
|
id = str_to_ints(line)[0]
|
||||||
res = 0
|
|
||||||
else:
|
|
||||||
res = 1
|
|
||||||
bps = []
|
bps = []
|
||||||
for line in input.text.replace(".", ".\n").replace(":", ":\n").splitlines():
|
maxmin = [0, 0, 0]
|
||||||
if "Blueprint" in line:
|
for part in line.split(". "):
|
||||||
bps.append([])
|
bp = []
|
||||||
elif "ore robot" in line:
|
for amount, mineral in re.findall(r"(\d+) (\w+)", part):
|
||||||
cost = str_to_ints(line)
|
amount = int(amount)
|
||||||
cost += [0, 0]
|
mi = ["ore", "clay", "obsidian", "geode"].index(mineral)
|
||||||
bps[-1].append(cost)
|
bp.append((amount, mi))
|
||||||
elif "clay robot" in line:
|
maxmin[mi] = max(maxmin[mi], amount)
|
||||||
cost = str_to_ints(line)
|
bps.append(bp)
|
||||||
cost += [0, 0]
|
|
||||||
bps[-1].append(cost)
|
|
||||||
elif "obsidian robot" in line:
|
|
||||||
cost = str_to_ints(line)
|
|
||||||
cost += [0,]
|
|
||||||
bps[-1].append(cost)
|
|
||||||
elif "geode robot" in line:
|
|
||||||
cost = str_to_ints(line)
|
|
||||||
cost.insert(1, 0)
|
|
||||||
bps[-1].append(cost)
|
|
||||||
|
|
||||||
if second:
|
def dfs(time, mins, bots, cache):
|
||||||
bps = bps[:3]
|
if time == 0:
|
||||||
time = 32
|
return mins[3]
|
||||||
|
|
||||||
|
key = (time, *mins, *bots)
|
||||||
|
if key in cache:
|
||||||
|
return cache[key]
|
||||||
|
|
||||||
|
maxv = mins[3] + time * bots[3]
|
||||||
|
for bi, recipe in enumerate(bps):
|
||||||
|
if bi != 3 and bots[bi] >= maxmin[bi]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
wait = 0
|
||||||
|
for ra, ri in recipe:
|
||||||
|
if bots[ri] == 0:
|
||||||
|
break
|
||||||
|
wait = max(ceil((ra - mins[ri]) / bots[ri]), wait)
|
||||||
else:
|
else:
|
||||||
time = 24
|
remtime = time - wait - 1
|
||||||
|
if remtime <= 0:
|
||||||
|
continue
|
||||||
|
|
||||||
end_states = []
|
bots_ = list(bots)
|
||||||
for i, bp in enumerate(bps):
|
mins_ = [m + b * (wait + 1) for m, b in zip(mins, bots)]
|
||||||
# ((ore bots, clay bots, obs bots, geo bots), (ore, clay, obs, geo))
|
for ra, ri in recipe:
|
||||||
start = ((1, 0, 0, 0), (0, 0, 0, 0))
|
mins_[ri] -= ra
|
||||||
states = [start]
|
bots_[bi] += 1
|
||||||
seen = set(states)
|
|
||||||
|
|
||||||
for _ in range(time):
|
for i in range(3):
|
||||||
new_states = []
|
mins_[i] = min(mins_[i], maxmin[i] * remtime)
|
||||||
while states:
|
v = dfs(remtime, tuple(mins_), tuple(bots_), cache)
|
||||||
bots, ress = states.pop()
|
maxv = max(v, maxv)
|
||||||
|
|
||||||
add_ress = [0, 0, 0, 0]
|
key = (time, *mins, *bots)
|
||||||
for boti, count in enumerate(bots):
|
cache[key] = maxv
|
||||||
add_ress[boti] += count
|
return maxv
|
||||||
|
|
||||||
all_built = True
|
p1 += id * dfs(24, (0, 0, 0, 0), (1, 0, 0, 0), {})
|
||||||
for boti, cost in enumerate(bp):
|
if id < 4:
|
||||||
if ress[0] >= cost[0] and ress[1] >= cost[1] and ress[2] >= cost[2]:
|
p2 *= dfs(32, (0, 0, 0, 0), (1, 0, 0, 0), {})
|
||||||
new_ress = list(ress)
|
|
||||||
new_ress[0] -= cost[0]
|
|
||||||
new_ress[1] -= cost[1]
|
|
||||||
new_ress[2] -= cost[2]
|
|
||||||
new_ress = tuple(map(sum, zip(new_ress, add_ress)))
|
|
||||||
new_bots = list(bots)
|
|
||||||
new_bots[boti] += 1
|
|
||||||
new_state = (tuple(new_bots), new_ress)
|
|
||||||
if not new_state in seen:
|
|
||||||
new_states.append(new_state)
|
|
||||||
seen.add(new_state)
|
|
||||||
else:
|
|
||||||
all_built = False
|
|
||||||
|
|
||||||
# XXX: our search space is too large here it is possible to
|
print(p1)
|
||||||
# optimze by not storing reduntant paths (paths where we acrue
|
print(p2)
|
||||||
# more of a resource than we need), but I don't know how to
|
|
||||||
# make it more efficient right now.
|
|
||||||
if not all_built:
|
|
||||||
new_ress = tuple(map(sum, zip(ress, add_ress)))
|
|
||||||
new_state = (bots, new_ress)
|
|
||||||
if not new_state in seen:
|
|
||||||
new_states.append(new_state)
|
|
||||||
seen.add(new_state)
|
|
||||||
|
|
||||||
# prune to keep search space "reasonable"
|
|
||||||
states = sorted(new_states, key=lambda s: list(reversed(s[0])), reverse=True)[:100000]
|
|
||||||
|
|
||||||
if not second:
|
|
||||||
r = max(states, key=lambda s: s[1][3])
|
|
||||||
q = (i + 1) * r[1][3]
|
|
||||||
# print(i + 1, r, q)
|
|
||||||
res += q
|
|
||||||
else:
|
|
||||||
r = max(states, key=lambda r: r[1][3])
|
|
||||||
res *= r[1][3]
|
|
||||||
return res
|
|
||||||
|
|
||||||
def main():
|
|
||||||
DAY_INPUT = "d19.txt"
|
|
||||||
e1 = solve(Input(EXAMPLE))
|
|
||||||
print("Example 1:", e1)
|
|
||||||
assert e1 == 33
|
|
||||||
print("Solution 1:", solve(Input(DAY_INPUT)))
|
|
||||||
print("Example 2:", solve(Input(EXAMPLE), True))
|
|
||||||
print("Solution 2:", solve(Input(DAY_INPUT), True))
|
|
||||||
return
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -108,7 +108,8 @@ Solutions and utility script for Advent of Code challenges in Python.
|
|||||||
- Day 18: 24:04
|
- Day 18: 24:04
|
||||||
- Day 19: days, super fun, but hard for me
|
- Day 19: days, super fun, but hard for me
|
||||||
- Day 20:
|
- Day 20:
|
||||||
- Day 21:
|
- Day 21: 28:40 (16th - brute force but still not so bad)
|
||||||
|
- Day 22:
|
||||||
|
|
||||||
## AoC 2019
|
## AoC 2019
|
||||||
|
|
||||||
@@ -146,7 +147,8 @@ Solutions and utility script for Advent of Code challenges in Python.
|
|||||||
- Day 9: 7:37 (choked bad)
|
- Day 9: 7:37 (choked bad)
|
||||||
- Day 10: 34:27 (so weak)
|
- Day 10: 34:27 (so weak)
|
||||||
- Day 11: 21:05 (hmmm, I rally have to analyze why I am so slow)
|
- Day 11: 21:05 (hmmm, I rally have to analyze why I am so slow)
|
||||||
- Day 12:
|
- Day 12: 21:52 (just slow again for an easy problem)
|
||||||
|
- Day 13:
|
||||||
|
|
||||||
|
|
||||||
## AoC 2022
|
## AoC 2022
|
||||||
@@ -154,10 +156,6 @@ Solutions and utility script for Advent of Code challenges in Python.
|
|||||||
Done with this. Overall everything is solvable. It's more about consistency
|
Done with this. Overall everything is solvable. It's more about consistency
|
||||||
and focus. Of course, learning more algorithms and techniques helps.
|
and focus. Of course, learning more algorithms and techniques helps.
|
||||||
|
|
||||||
Possible to-dos:
|
|
||||||
|
|
||||||
- [ ] Optimize day 19 because it is terrible.
|
|
||||||
|
|
||||||
**Times:**
|
**Times:**
|
||||||
|
|
||||||
- Day 1: 7:52 ... so slow brah :/ top 100 required 2:05...
|
- Day 1: 7:52 ... so slow brah :/ top 100 required 2:05...
|
||||||
@@ -184,7 +182,7 @@ Possible to-dos:
|
|||||||
LEADERBOARD?!?!?!?!?!?!?!
|
LEADERBOARD?!?!?!?!?!?!?!
|
||||||
- Day 17: Second one was fun with having to detect the repetition.
|
- Day 17: Second one was fun with having to detect the repetition.
|
||||||
- Day 18: 12:00 and 32:00; really straightforward and of course way too slow.
|
- Day 18: 12:00 and 32:00; really straightforward and of course way too slow.
|
||||||
- Day 19: Slow.
|
- Day 19: Slow. (2024-09-13 improved with help from hyper neutrino.)
|
||||||
- Day 20: Struggled way too much.
|
- Day 20: Struggled way too much.
|
||||||
- Day 21: Straightforward and relatively fast.
|
- Day 21: Straightforward and relatively fast.
|
||||||
- Day 22: Very hard and wasn't able to do hands free. Even the best guys took
|
- Day 22: Very hard and wasn't able to do hands free. Even the best guys took
|
||||||
|
|||||||
Reference in New Issue
Block a user