diff --git a/day16/sol.py b/day16/sol.py index 163307d..1c0bbc4 100644 --- a/day16/sol.py +++ b/day16/sol.py @@ -30,49 +30,194 @@ def save(): #import astar -score = {'AA': (0, 0, [])} +def part1(): + score = {'AA': (0, 0, [])} -# find the largest reward we can get in n steps -# then find the largest reward we can get in n+1 steps -potential = sum(r for _,r,_ in G) -minutes = 30 -for _ in range(minutes): - minutes -= 1 - next = {} - for v, r, E in G: - vo = v + 'o' - s = [] - o = [] - if vo in score: - reward, flow, open = score[vo] - o.append((reward, flow, open)) - if v in score: - reward, flow, open = score[v] - # stay, don't open valve - s.append((reward, flow, open)) - # stay in place, open valve - if v not in open: - reward += r*minutes - o.append((reward, flow+r, open+[v])) - # move here from somewhere else + minutes = 30 + for _ in range(minutes): + minutes -= 1 + next = {} + for v, r, E in G: + vo = v + 'o' + s = [] + o = [] + if vo in score: + reward, flow, open = score[vo] + o.append((reward, flow, open)) + if v in score: + reward, flow, open = score[v] + # stay, don't open valve + s.append((reward, flow, open)) + # stay in place, open valve + if v not in open: + reward += r*minutes + o.append((reward, flow+r, open+[v])) + # move here from somewhere else + for e in E: + if e in score: + if v in score[e][-1]: + o.append(score[e]) + else: + s.append(score[e]) + eo = e+'o' + if eo in score: + if v in score[eo][-1]: + o.append(score[eo]) + else: + s.append(score[eo]) + if s: + next[v] = max(s) + if o: + next[vo] = max(o) + score = next + print("%d minutes left" % minutes) + for v, (r, flow, open) in sorted(score.items(), key=lambda x: x[1]): + print("\t", v, r, "\t", ",".join(open)) + print(max(r for r,_,_ in score.values())) + +def part2(): + H = {x[0]: x for x in G} + def actions(v, open): + _, r, E = H[v] + if v in open: + yield (v, 0, []) + else: + yield (v, 0, []) + yield (v+'o', r, [v]) + # move to somewhere else for e in E: - if e in score: - if v in score[e][-1]: - o.append(score[e]) - else: - s.append(score[e]) - eo = e+'o' - if eo in score: - if v in score[eo][-1]: - o.append(score[eo]) - else: - s.append(score[eo]) - if s: - next[v] = max(s) - if o: - next[vo] = max(o) - score = next - print("%d minutes left" % minutes) - for v, (r, flow, open) in sorted(score.items(), key=lambda x: x[1]): - print("\t", v, r, "\t", ",".join(open)) -print(max(r for r,_,_ in score.values())) + if e in open: + e = e+'o' + yield (e, 0, []) + + score = {('AA', 'AA'): (0, 0, [])} + minutes = 26 + for _ in range(minutes): + next = {} + minutes -= 1 + + for (me, elephant) in score: + reward, flow, open = score[(me, elephant)] + for v, r, o in actions(me.strip('o'), open): + for v1, r1, o1 in actions(elephant.strip('o'), open+o): + reward_ = reward + (r+r1)*minutes + flow_ = flow + r + r1 + open_ = open + o + o1 + next.setdefault((v, v1), []).append((reward_, flow_, open_)) + + for k in next: + next[k] = max(next[k]) + + score = next + print("%d minutes left" % minutes) + for v, (r, flow, open) in sorted(score.items(), key=lambda x: x[1]): + print("\t", v, r, "\t", ",".join(open)) + print(max(r for r,_,_ in score.values())) + +#part2() + +def part2_b(): + score = {'AA': (0, 0, [])} + + minutes = 26 + for _ in range(minutes): + minutes -= 1 + next = {} + for v, r, E in G: + vo = v + 'o' + s = [] + o = [] + if vo in score: + reward, flow, open = score[vo] + o.append((reward, flow, open)) + if v in score: + reward, flow, open = score[v] + # stay, don't open valve + s.append((reward, flow, open)) + # stay in place, open valve + if v not in open: + reward += r*minutes + o.append((reward, flow+r, open+[v])) + # move here from somewhere else + for e in E: + if e in score: + if v in score[e][-1]: + o.append(score[e]) + else: + s.append(score[e]) + eo = e+'o' + if eo in score: + if v in score[eo][-1]: + o.append(score[eo]) + else: + s.append(score[eo]) + if s: + next[v] = max(s) + if o: + next[vo] = max(o) + score = next + print("%d minutes left" % minutes) + for v, (r, flow, open) in sorted(score.items(), key=lambda x: x[1]): + print("\t", v, r, "\t", ",".join(open)) + + maxpair = [] + for r,_,open in score.values(): + o = frozenset(open) + for s,_,open in score.values(): + if o.isdisjoint(open): + maxpair.append(r+s) + print(max(maxpair)) + +#part2_b() + +def part2_c(): + V = sorted(v for v,_,_ in G) + B = {v: 1<= r: + continue + best[o] = r + + maxpair = [] + def pairs(): + O = sorted(best.keys()) + for i in range(len(O)): + for j in range(i,len(O)): + if not O[i] & O[j]: + yield(best[O[i]]+best[O[j]]) + print(max(pairs())) + +part2_c()