Solve 2018 day 21, 2020 day 12 and improve 2022 day 19

This commit is contained in:
2024-09-13 20:22:22 -04:00
parent 9cd17279d9
commit 4a72eeb348
4 changed files with 192 additions and 111 deletions

52
2018/d21.py Normal file
View 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
View 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()

View File

@@ -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()

View File

@@ -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