Advertisement
nairby

Day 21 Code

Dec 21st, 2021
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.36 KB | None | 0 0
  1. use std::env;
  2. use std::io::{self};
  3.  
  4. const CIRCLE_SIZE: u64 = 10;
  5. const DICE_ROLLS_PER_TURN: u64 = 3;
  6.  
  7. const DETERM_DICE_SIDES: u64 = 100;
  8. const WIN_SCORE_PART1: u64 = 1000;
  9.  
  10. const WIN_SCORE_PART2: u64 = 21;
  11.  
  12. fn add_arrays(first: [u64;2], second: [u64;2]) -> [u64;2] {
  13.     let mut new: [u64;2] = [0;2];
  14.     new[0] = first[0] + second[0];
  15.     new[1] = first[1] + second[1];
  16.     new
  17. }
  18.  
  19. #[macro_use] extern crate lazy_static;
  20. lazy_static! {
  21.     static ref ROLLS: Vec<[u64; 3]> = {
  22.         let mut poss: Vec<[u64; 3]> = Vec::new();
  23.         for d1 in 1..=3 {
  24.             for d2 in 1..=3 {
  25.                 for d3 in 1..=3 {
  26.                     poss.push([d1, d2, d3]);
  27.                 }
  28.             }
  29.         }
  30.         poss
  31.     };
  32. }
  33.  
  34. #[macro_use] extern crate cached;
  35.  
  36. cached! {
  37.     PD;
  38.     fn play_from(starting: [u64;2], scores: [u64;2], turn: usize, rolls: Option<[u64; 3]>) -> [u64; 2] = {
  39.         let mut wins: [u64; 2] = [0; 2];
  40.  
  41.         // Initialize game
  42.         let mut pos:   [u64; 2] = starting;
  43.         let mut score: [u64; 2] = scores;
  44.  
  45.         // Play next move first
  46.         match rolls {
  47.             Some(roll) => {
  48.                 pos[turn] = (pos[turn] + roll[0]+roll[1]+roll[2] - 1) % CIRCLE_SIZE + 1;
  49.                 score[turn] += pos[turn];
  50.                 if score[turn] >= WIN_SCORE_PART2 {
  51.                     wins[turn] += 1;
  52.                     return wins;
  53.                 }
  54.             },
  55.             _ => {},
  56.         }
  57.  
  58.         // Keep playing
  59.         let player = if turn == 0 { 1 } else { 0 };
  60.         for roll in ROLLS.iter() {
  61.             wins = add_arrays(wins,play_from(pos,score, player, Some(*roll)));
  62.         }
  63.         wins
  64.     }
  65. }
  66.  
  67. fn play_part1(starting: [u64;2]) -> u64 {
  68.     // Play game
  69.     let mut pos:   [u64; 2] = starting;
  70.     let mut score: [u64; 2] = [0; 2];
  71.     let mut rolls = 0;
  72.     let mut dice = 0;
  73.     'play: loop {
  74.  
  75.        // Player Loop
  76.        for player in 0..2 {
  77.            let mut roll = 0;
  78.            for _ in 0..DICE_ROLLS_PER_TURN {
  79.                dice += 1;
  80.                if dice > DETERM_DICE_SIDES { dice = 1; }
  81.                roll += dice;
  82.            }
  83.            pos[player] = (pos[player] + roll - 1) % CIRCLE_SIZE + 1;
  84.            score[player] += pos[player];
  85.            rolls += DICE_ROLLS_PER_TURN;
  86.            if score[player] >= WIN_SCORE_PART1 { break 'play; }
  87.         }
  88.     }
  89.     let loser = score.iter().min().unwrap();
  90.     loser * rolls
  91. }
  92.  
  93. fn solve(input: &str) -> io::Result<()> {
  94.     // Input
  95.     let input_str = std::fs::read_to_string(input).unwrap();
  96.     let input_str = input_str.trim();
  97.    
  98.     // Starting positions
  99.     let starting = input_str
  100.         .split("\n")
  101.         .map(|l| l.chars().last().unwrap().to_digit(10).unwrap())
  102.         .collect::<Vec<_>>();
  103.  
  104.     let starting: [u64; 2] = [starting[0].into(), starting[1].into()];
  105.  
  106.     // Part 1
  107.     let part1 = play_part1(starting.into());
  108.     println!("Part 1: {}", part1); // 1004670
  109.  
  110.     // Part 2
  111.     let part2 = play_from(starting, [0;2], 1, None); // start with player 1 because rolls=None (effectively starts with player 0)
  112.     let part2 = part2.iter().max().unwrap();
  113.     println!("Part 2: {}", part2); // 492043106122795
  114.  
  115.     Ok(())
  116. }
  117.  
  118. fn main() {
  119.     let args: Vec<String> = env::args().collect();
  120.     let filename = &args[1];
  121.     solve(&filename).unwrap();
  122. }
  123.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement