diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2021-12-21 11:52:37 +0000 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2021-12-21 11:52:37 +0000 |
commit | 68bc22ce3139786fc6b39dab95dbe83d5cc486ef (patch) | |
tree | 2b35306dc1914492a0aa7bf894ed3eec8da167eb | |
parent | d0085fa59347640e202a0f8c1ace272406caa7f0 (diff) | |
download | aoc2021-68bc22ce3139786fc6b39dab95dbe83d5cc486ef.tar.gz aoc2021-68bc22ce3139786fc6b39dab95dbe83d5cc486ef.tar.xz aoc2021-68bc22ce3139786fc6b39dab95dbe83d5cc486ef.zip |
day 21
-rw-r--r-- | 21.py | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -0,0 +1,39 @@ +from itertools import count +from re import compile as re_compile +from utils import open_day +from functools import cache, reduce + +pattern = re_compile(r'Player \d+ starting position: (\d+)') +with open_day(21) as f: + positions = tuple(int(pattern.match(line).group(1)) - 1 for line in f) + +def part1(positions): + poss = list(positions) + scores = [0 for _ in poss] + for roll in count(): + rolled = (3 * roll + 1) * 3 + 3 + player = roll % len(poss) + poss[player] += rolled + poss[player] %= 10 + scores[player] += poss[player] + 1 + if scores[player] >= 1000: + return [score * (roll + 1) * 3 for score in scores if score < 1000][0] + +@cache +def part2(positions, scores=(0, 0), player=0, maxscore=21): + dirac_triples = ((1, 3), (3, 4), (6, 5), (7, 6), (6, 7), (3, 8), (1, 9)) + def times(t, c): return (t[0] * c, t[1] * c) + def tupsum(a, b): return (a[0] + b[0], a[1] + b[1]) + def turn(rolled): + nposs = list(positions) + nscores = list(scores) + nposs[player] += rolled + nposs[player] %= 10 + nscores[player] += nposs[player] + 1 + if nscores[player] >= maxscore: + return (player == 0, player != 0) + return part2(tuple(nposs), tuple(nscores), int(not player), maxscore) + return reduce(tupsum, (times(turn(roll), count) for count, roll in dirac_triples)) + +print(part1(positions)) +print(max(part2(positions))) |