Advertisement
illuminati229

AoC Day 21

Dec 21st, 2021
366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.19 KB | None | 0 0
  1. from functools import cache
  2. from time import perf_counter
  3.  
  4. moves = []
  5. for i in range(1,4):
  6.     for j in range(1,4):
  7.         for k in range(1,4):
  8.             moves.append(sum([i,j,k]))
  9.  
  10. @cache
  11. def quantom_roll(p1_pos, p2_pos, p1_score, p2_score, move, p1_roll):
  12.     if p1_roll:        
  13.         p1_pos = (p1_pos + move - 1) % 10 + 1
  14.         p1_score += p1_pos
  15.         if p1_score >= 21:
  16.             return (1, 0)
  17.         p1_roll = False
  18.     else:
  19.         p2_pos = (p2_pos + move - 1) % 10 + 1
  20.         p2_score += p2_pos
  21.         if p2_score >= 21:
  22.             return (0, 1)
  23.         p1_roll = True
  24.                
  25.     subgames = [quantom_roll(p1_pos, p2_pos, p1_score, p2_score, move, p1_roll) for move in moves]
  26.  
  27.     return sum([a for a, _ in subgames]), sum([b for _, b in subgames])
  28.                    
  29.  
  30. def real_dirac_dice(file_path):
  31.    
  32.     with open(file_path) as fin:
  33.         p1, p2 = [int(line.strip()[-1]) for line in fin.readlines()]
  34.  
  35.     p1_wins, p2_wins = quantom_roll(p1, p2, 0, -p2, 0, False)
  36.     return max(p1_wins, p2_wins)
  37.  
  38. def dirac_dice(file_path, win_score):
  39.  
  40.     with open(file_path) as fin:
  41.         p1, p2 = [int(line.strip()[-1]) for line in fin.readlines()]
  42.  
  43.     p1_score = 0
  44.     p2_score = 0
  45.  
  46.     moves = [(i % 10) for i in range(16, 6, -1)]
  47.  
  48.     board = [i for i in range(1,11)]
  49.  
  50.     p1_pos = board.index(p1)
  51.     p2_pos = board.index(p2)
  52.  
  53.     roll = 0
  54.  
  55.     while True:
  56.         p1_pos += moves[roll % 10]
  57.         p1_score += board[p1_pos % 10]
  58.         roll += 1
  59.         if p1_score >= win_score:
  60.             break
  61.        
  62.         p2_pos += moves[roll % 10]
  63.         p2_score += board[p2_pos % 10]
  64.         roll += 1
  65.         if p2_score >= win_score:
  66.             break
  67.  
  68.     return roll * 3 *  min(p1_score, p2_score)
  69.  
  70. def main():
  71.  
  72.     assert dirac_dice('test_input.txt', 1000) == 739785
  73.     print(dirac_dice('input.txt', 1000))
  74.  
  75.     start = perf_counter()
  76.     assert real_dirac_dice('test_input.txt') == 444356092776315
  77.     print('Test time:', perf_counter() - start)
  78.  
  79.     start = perf_counter()
  80.     print(real_dirac_dice('input.txt'))
  81.     print('Actual time:', perf_counter() - start)
  82.  
  83.    
  84. if __name__ == '__main__':
  85.     main()
  86.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement