|
@@ -0,0 +1,72 @@
|
|
|
+from itertools import product
|
|
|
+
|
|
|
+#input = [4, 8]
|
|
|
+input = [1, 5]
|
|
|
+
|
|
|
+pos = [input[0] - 1, input[1] - 1]
|
|
|
+score = [0, 0]
|
|
|
+turn = 0
|
|
|
+
|
|
|
+dice = 1
|
|
|
+rolls = 0
|
|
|
+
|
|
|
+def roll():
|
|
|
+ global dice
|
|
|
+ global rolls
|
|
|
+ res = dice
|
|
|
+ dice += 1
|
|
|
+ rolls += 1
|
|
|
+ if dice == 101:
|
|
|
+ dice = 1
|
|
|
+ return res
|
|
|
+
|
|
|
+def roll3():
|
|
|
+ global dice
|
|
|
+ global rolls
|
|
|
+ if dice < 98:
|
|
|
+ res = dice * 3 + 3
|
|
|
+ dice += 3
|
|
|
+ rolls += 3
|
|
|
+ return res
|
|
|
+ else:
|
|
|
+ return roll() + roll() + roll()
|
|
|
+
|
|
|
+while score[0] < 1000 and score[1] < 1000:
|
|
|
+ for i in range(2):
|
|
|
+ pos[i] += roll3()
|
|
|
+ pos[i] = pos[i] % 10
|
|
|
+ score[i] += pos[i] + 1
|
|
|
+ if score[i] >= 1000:
|
|
|
+ print("Part 1:", score[(i + 1) % 2] * rolls)
|
|
|
+
|
|
|
+wincount = {}
|
|
|
+
|
|
|
+def calc_wincount(state):
|
|
|
+ (pos, score, turn) = state
|
|
|
+ wc = [0, 0]
|
|
|
+ if score[0] >= 21:
|
|
|
+ return [1, 0]
|
|
|
+ elif score[1] >= 21:
|
|
|
+ return [0, 1]
|
|
|
+ for [a, b, c] in product(list(range(1, 4)), repeat=3):
|
|
|
+ steps = a + b + c
|
|
|
+ if turn == 0:
|
|
|
+ newpos = ((pos[0] + steps) % 10, pos[1])
|
|
|
+ newscore = (score[0] + newpos[0] + 1, score[1])
|
|
|
+ else:
|
|
|
+ newpos = (pos[0], (pos[1] + steps) % 10)
|
|
|
+ newscore = (score[0], score[1] + newpos[1] + 1)
|
|
|
+ [c1, c2] = wincount[(newpos, newscore, (turn + 1) % 2)]
|
|
|
+ wc[0] += c1
|
|
|
+ wc[1] += c2
|
|
|
+ return wc
|
|
|
+
|
|
|
+for ascore in reversed(range(0, 31)):
|
|
|
+ for bscore in reversed(range(0, 31)):
|
|
|
+ for turn in range(2):
|
|
|
+ for apos in range(0, 10):
|
|
|
+ for bpos in range(0, 10):
|
|
|
+ state = ((apos, bpos), (ascore, bscore), turn)
|
|
|
+ wincount[state] = calc_wincount(state)
|
|
|
+
|
|
|
+print("Part 2:", max(wincount[((input[0] - 1, input[1] - 1), (0, 0), 0)]))
|