summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBrian Chu <brianmchu42@gmail.com>2021-12-21 00:03:42 -0800
committerBrian Chu <brianmchu42@gmail.com>2021-12-21 00:03:42 -0800
commit9baba38544e5caf3986576096e2e4c44497530bd (patch)
tree9c57c1bc293e0f668b7155a5c8105c4bcf697ee3
parentd4f482804b9777768fa4f9fedde0cd549578502b (diff)
downloadAdventOfCode2021-9baba38544e5caf3986576096e2e4c44497530bd.tar.gz
solution for day 21
-rw-r--r--day21.py87
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))