fork download
  1. use std::collections::BTreeMap;
  2.  
  3. type Win = BTreeMap<GameState, (usize, usize)>;
  4.  
  5. fn main() {
  6. let mut rolls: BTreeMap<u32, usize> = BTreeMap::new();
  7. for r1 in 1..=3 {
  8. for r2 in 1..=3 {
  9. for r3 in 1..=3 {
  10. let roll = r1 + r2 + r3;
  11. *rolls.entry(roll).or_insert(0) += 1;
  12. }
  13. }
  14. }
  15. let mut wins: Win = BTreeMap::new();
  16. let game = Game::new(4, 8, 21).play_quantum(&rolls, &mut wins);
  17. println!("{:?} , {:?}", game.0, game.1);
  18. let game = Game::new(3, 7, 1000).play_deterministic();
  19. println!("{:?}", game.game_score);
  20. }
  21.  
  22. #[derive(Debug, Eq, Ord, PartialOrd, PartialEq, Clone, Copy, Hash)]
  23. struct GameState {
  24. win_score: u32,
  25. track_len: u32,
  26. player1: PlayerState,
  27. player2: PlayerState,
  28. }
  29.  
  30. #[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, PartialOrd, Ord)]
  31. enum Player {
  32. One,
  33. Two,
  34. }
  35.  
  36. #[derive(Debug, Eq, PartialEq, Clone, Copy)]
  37. struct Game {
  38. won: Option<Player>,
  39. game_score: Option<u32>,
  40. state: GameState,
  41. dices_rolled: u32,
  42. dice: Dice,
  43. }
  44.  
  45. #[derive(Debug, Eq, PartialEq, Clone, Copy)]
  46. struct Dice {
  47. last_roll: u32,
  48. }
  49.  
  50. #[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, PartialOrd, Ord)]
  51. struct PlayerState {
  52. id: Player,
  53. pos: u32,
  54. score: u32,
  55. rolled: u32,
  56. }
  57.  
  58. impl Game {
  59. fn new(position1: u32, position2: u32, win_score: u32) -> Self {
  60. Game {
  61. won: None,
  62. game_score: None,
  63. state: GameState {
  64. win_score,
  65. track_len: 10,
  66. player1: PlayerState {
  67. id: Player::One,
  68. pos: position1,
  69. score: 0,
  70. rolled: 0,
  71. },
  72. player2: PlayerState {
  73. id: Player::Two,
  74. pos: position2,
  75. score: 0,
  76. rolled: 0,
  77. },
  78. },
  79. dices_rolled: 0,
  80. dice: Dice { last_roll: 1 },
  81. }
  82. }
  83.  
  84. fn play_deterministic(&self) -> Self {
  85. let mut result: Game = *self;
  86. loop {
  87. let roll1 = result.dice.roll_d();
  88. let roll2 = result.dice.roll_d();
  89. let (state, rolled) = round(&(roll1, roll2), &result.state);
  90. result.dices_rolled += rolled;
  91. result.state = state;
  92. if result.is_win() {
  93. return result;
  94. }
  95. }
  96. }
  97.  
  98. fn play_quantum(&self, rolls: &BTreeMap<u32, usize>, win_map: &mut Win) -> (usize, usize) {
  99. let mut wins = (0, 0);
  100.  
  101. for (roll1, count1) in rolls.iter() {
  102. for (roll2, count2) in rolls.iter() {
  103. let (win1, win2) = self.quantum_game(&(*roll1, *roll2), win_map, rolls);
  104. let mult = count1 * count2;
  105. wins.0 += mult * win1;
  106. if win1 == 1 && win2 == 0 {
  107. break;
  108. }
  109. wins.1 += mult * win2;
  110. }
  111. }
  112. wins
  113. }
  114.  
  115. fn quantum_game(
  116. &self,
  117. entry: &(u32, u32),
  118. win_map: &mut BTreeMap<GameState, (usize, usize)>,
  119. rolls: &BTreeMap<u32, usize>,
  120. ) -> (usize, usize) {
  121. let mut result: Game = *self;
  122. let (state, _rolled) = round(entry, &result.state);
  123. result.state = state;
  124. if !result.is_win() {
  125. if let Some(x) = win_map.get(&state) {
  126. *x
  127. } else {
  128. let tmp = result.play_quantum(rolls, win_map);
  129. return *win_map.entry(state).or_insert(tmp);
  130. }
  131. } else if result.won == Some(Player::One) {
  132. (1, 0)
  133. } else if result.won == Some(Player::Two) {
  134. (0, 1)
  135. } else {
  136. (0, 0)
  137. }
  138. }
  139.  
  140. fn is_win(&mut self) -> bool {
  141. if self.state.player1.score >= self.state.win_score {
  142. self.won = Some(Player::One);
  143. self.game_score = Some(self.state.player2.score * self.dices_rolled);
  144. true
  145. } else if self.state.player2.score >= self.state.win_score {
  146. self.won = Some(Player::Two);
  147. self.game_score = Some(self.state.player1.score * self.dices_rolled);
  148. true
  149. } else {
  150. false
  151. }
  152. }
  153. }
  154.  
  155. impl Dice {
  156. fn roll_d(&mut self) -> u32 {
  157. let roll = self.last_roll;
  158. let roll = 3 * roll + 3;
  159. self.last_roll += 3;
  160. roll
  161. }
  162. }
  163.  
  164. impl PlayerState {
  165. fn new_position(&self, track_len: u32, roll: u32) -> u32 {
  166. let pos = (self.pos + roll) % track_len;
  167. if pos == 0 {
  168. track_len
  169. } else {
  170. pos
  171. }
  172. }
  173.  
  174. fn rolled(&mut self, track_len: u32, roll: u32) {
  175. self.pos = self.new_position(track_len, roll);
  176. self.score += self.pos;
  177. }
  178. }
  179.  
  180. type Roll = (u32, u32);
  181.  
  182. fn round(dice_roll: &Roll, state: &GameState) -> (GameState, u32) {
  183. let mut new_state = *state;
  184. new_state.player1.rolled(state.track_len, dice_roll.0);
  185. if new_state.player1.score >= state.win_score {
  186. return (new_state, 3);
  187. }
  188. new_state.player2.rolled(state.track_len, dice_roll.1);
  189. (new_state, 6)
  190. }
  191.  
Success #stdin #stdout 0.12s 5448KB
stdin
Standard input is empty
stdout
444356092776315 , 341960390180808
Some(1006866)