aboutsummaryrefslogtreecommitdiff
path: root/2021/day21
diff options
context:
space:
mode:
Diffstat (limited to '2021/day21')
-rw-r--r--2021/day21/21.py52
-rw-r--r--2021/day21/21b.py55
2 files changed, 107 insertions, 0 deletions
diff --git a/2021/day21/21.py b/2021/day21/21.py
new file mode 100644
index 0000000..8cd8307
--- /dev/null
+++ b/2021/day21/21.py
@@ -0,0 +1,52 @@
+
+die_val = 1
+rolls = 0
+def roll():
+ global die_val, rolls
+ x = die_val
+
+ die_val += 1
+ if die_val > 100:
+ die_val = 1
+
+ rolls += 1
+
+ return x
+
+
+class Player:
+ def __init__(self, pos):
+ self.pos = pos
+ self.score = 0
+
+ def move(self, roll):
+ self.pos += roll
+ while self.pos > 10:
+ self.pos -= 10
+
+ def take_turn(self):
+ r = sum([roll() for _ in range(0, 3)])
+ self.move(r)
+ self.score += self.pos
+
+ def __str__(self):
+ return "<Player pos=%d score=%d>" % (self.pos, self.score)
+
+inp = open("./input").read().split("\n")
+p1_start = int(inp[0].split(": ")[1])
+p2_start = int(inp[1].split(": ")[1])
+
+p1 = Player(p1_start)
+p2 = Player(p2_start)
+turn = p1
+while p1.score < 1000 and p2.score < 1000:
+ turn.take_turn()
+ if turn == p1:
+ turn = p2
+ else:
+ turn = p1
+
+ans = p1.score * rolls
+if p1.score >= 1000:
+ ans = p2.score * rolls
+print("Part 1: %d" % ans)
diff --git a/2021/day21/21b.py b/2021/day21/21b.py
new file mode 100644
index 0000000..3404c22
--- /dev/null
+++ b/2021/day21/21b.py
@@ -0,0 +1,55 @@
+from collections import defaultdict
+
+POSSIBLE_ROLLS = [a + b + c for a in range(1, 4) for b in range(1, 4) for c in range(1, 4)]
+
+def move(p, roll):
+ pos, score = p
+ pos += roll
+ while pos > 10:
+ pos -= 10
+
+ return (pos, score + pos)
+
+def won(p):
+ return p[1] >= 21
+
+P1_WON_KEY = (-1, -1, True)
+P2_WON_KEY = (-1, -1, False)
+
+def step_universes(d):
+ nxt = defaultdict(lambda: 0)
+ nxt[P1_WON_KEY] = d[P1_WON_KEY]
+ nxt[P2_WON_KEY] = d[P2_WON_KEY]
+ for ((p1, p2, p1_turn), count) in d.items():
+ if p1 == -1:
+ continue
+ elif won(p1):
+ nxt[P1_WON_KEY] += count
+ continue
+ elif won(p2):
+ nxt[P2_WON_KEY] += count
+ continue
+
+ for roll in POSSIBLE_ROLLS:
+ if p1_turn:
+ nxt[(move(p1, roll), p2, False)] += count
+ else:
+ nxt[(p1, move(p2, roll), True)] += count
+
+ return nxt
+
+inp = open("./input").read().split("\n")
+p1_start = int(inp[0].split(": ")[1])
+p2_start = int(inp[1].split(": ")[1])
+
+d = defaultdict(lambda: 0)
+d[((p1_start, 0), (p2_start, 0), True)] = 1
+d = step_universes(d)
+
+while len(d) > 2:
+ d = step_universes(d)
+
+w1 = d[P1_WON_KEY]
+w2 = d[P2_WON_KEY]
+print("Part 2: %d" % max([w1, w2]))
+