123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- 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)]))
|