/ Python / 2021 / 21.py
21.py
 1  from lib import *
 2  
 3  input = read_input(2021, 21)
 4  
 5  lines = input.splitlines()
 6  
 7  
 8  players = [int(line.split()[-1]) for line in lines]
 9  scores = [0, 0]
10  die = 0
11  k = 0
12  while max(scores) < 1000:
13      x = sum((die + i) % 100 + 1 for i in range(3))
14      die += 3
15      players[k] = (players[k] - 1 + x) % 10 + 1
16      scores[k] += players[k]
17      k = (k + 1) % 2
18  
19  print(scores[k] * die)
20  
21  
22  @functools.cache
23  def dirac(p1, p2, s1, s2, k):
24      if s1 >= 21:
25          return 1, 0
26  
27      if s2 >= 21:
28          return 0, 1
29  
30      p = [p1, p2][k]
31      s = [s1, s2][k]
32      out = [0, 0]
33      for x in map(sum, itertools.product([1, 2, 3], repeat=3)):
34          q = (p - 1 + x) % 10 + 1
35          if k == 0:
36              res = dirac(q, p2, s + q, s2, 1)
37          else:
38              res = dirac(p1, q, s1, s + q, 0)
39          for i in range(2):
40              out[i] += res[i]
41  
42      return tuple(out)
43  
44  
45  dirac.cache_clear()
46  players = [int(line.split()[-1]) for line in lines]
47  print(max(dirac(*players, 0, 0, 0)))