21.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. from itertools import product
  2. #input = [4, 8]
  3. input = [1, 5]
  4. pos = [input[0] - 1, input[1] - 1]
  5. score = [0, 0]
  6. turn = 0
  7. dice = 1
  8. rolls = 0
  9. def roll():
  10. global dice
  11. global rolls
  12. res = dice
  13. dice += 1
  14. rolls += 1
  15. if dice == 101:
  16. dice = 1
  17. return res
  18. def roll3():
  19. global dice
  20. global rolls
  21. if dice < 98:
  22. res = dice * 3 + 3
  23. dice += 3
  24. rolls += 3
  25. return res
  26. else:
  27. return roll() + roll() + roll()
  28. while score[0] < 1000 and score[1] < 1000:
  29. for i in range(2):
  30. pos[i] += roll3()
  31. pos[i] = pos[i] % 10
  32. score[i] += pos[i] + 1
  33. if score[i] >= 1000:
  34. print("Part 1:", score[(i + 1) % 2] * rolls)
  35. wincount = {}
  36. def calc_wincount(state):
  37. (pos, score, turn) = state
  38. wc = [0, 0]
  39. if score[0] >= 21:
  40. return [1, 0]
  41. elif score[1] >= 21:
  42. return [0, 1]
  43. for [a, b, c] in product(list(range(1, 4)), repeat=3):
  44. steps = a + b + c
  45. if turn == 0:
  46. newpos = ((pos[0] + steps) % 10, pos[1])
  47. newscore = (score[0] + newpos[0] + 1, score[1])
  48. else:
  49. newpos = (pos[0], (pos[1] + steps) % 10)
  50. newscore = (score[0], score[1] + newpos[1] + 1)
  51. [c1, c2] = wincount[(newpos, newscore, (turn + 1) % 2)]
  52. wc[0] += c1
  53. wc[1] += c2
  54. return wc
  55. for ascore in reversed(range(0, 31)):
  56. for bscore in reversed(range(0, 31)):
  57. for turn in range(2):
  58. for apos in range(0, 10):
  59. for bpos in range(0, 10):
  60. state = ((apos, bpos), (ascore, bscore), turn)
  61. wincount[state] = calc_wincount(state)
  62. print("Part 2:", max(wincount[((input[0] - 1, input[1] - 1), (0, 0), 0)]))