diff options
author | Brian Chu <brianmchu42@gmail.com> | 2021-12-21 00:03:42 -0800 |
---|---|---|
committer | Brian Chu <brianmchu42@gmail.com> | 2021-12-21 00:03:42 -0800 |
commit | 9baba38544e5caf3986576096e2e4c44497530bd (patch) | |
tree | 9c57c1bc293e0f668b7155a5c8105c4bcf697ee3 | |
parent | d4f482804b9777768fa4f9fedde0cd549578502b (diff) | |
download | AdventOfCode2021-9baba38544e5caf3986576096e2e4c44497530bd.tar.gz |
solution for day 21
-rw-r--r-- | day21.py | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/day21.py b/day21.py new file mode 100644 index 0000000..524f557 --- /dev/null +++ b/day21.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +# input: player 1 starts at 3, player 2 starts at 5 + +class Die(): + def __init__(self): + self.curr = 0 + self.rolls = 0 + + def __iter__(self): + return self + + def __next__(self): + result = 0 + for _ in range(3): + self.curr += 1 + if self.curr > 100: + self.curr = 1 + result += self.curr + self.rolls += 3 + return result % 10 + + def get_rolls(self): + return self.rolls + +class Player(): + def __init__(self, pos): + self.pos = pos + self.score = 0 + + def advance(self, dPos): + self.pos += dPos + self.pos %= 10 + if self.pos == 0: + self.pos = 10 + self.score += self.pos + + def win(self): + return self.score >= 1000 + + def get_score(self): + return self.score + +def part1(): + player1 = Player(3) + player2 = Player(5) + die = Die() + isPlayer1 = True + for roll in die: + if isPlayer1: + player1.advance(roll) + else: + player2.advance(roll) + isPlayer1 = not isPlayer1 + if player1.win() or player2.win(): + losing_score = min(player1.get_score(), player2.get_score()) + print(losing_score * die.get_rolls()) + break + +# part 2 +from collections import namedtuple, Counter +from functools import cache +from itertools import product +tPlayer = namedtuple('tPlayer', ['pos', 'score']) +rolls = Counter(sum(t) for t in product([1, 2, 3], repeat=3)) + +@cache +def part2(players, playerNum): + wins = [0, 0] + for roll, count in rolls.items(): + innerPlayers = list(players) + pos, score = players[playerNum] + pos = (pos + roll - 1) % 10 + 1 + score += pos + if score >= 21: + wins[playerNum] += count + else: + innerPlayers[playerNum] = tPlayer(pos, score) + recWins = part2(tuple(innerPlayers), (playerNum + 1)%2) + for i in range(2): + wins[i] += recWins[i] * count + return wins + +if __name__ == '__main__': + part1() + wins = part2((tPlayer(3, 0), tPlayer(5, 0)), 0) + print(max(wins)) |