Advertisement
tech_hutch

Untitled

Dec 11th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.05 KB | None | 0 0
  1. extern crate chrono;
  2.  
  3. use chrono::DateTime;
  4. use chrono::offset::Utc;
  5.  
  6. type Marble = u32;
  7.  
  8. trait MarbleTrait {
  9.     fn is_scoring(&self) -> bool;
  10. }
  11.  
  12. impl MarbleTrait for Marble {
  13.     fn is_scoring(&self) -> bool {
  14.         self % 23 == 0
  15.     }
  16. }
  17.  
  18. struct Circle {
  19.     vec: Vec<Marble>,
  20.     current_i: usize,
  21. }
  22.  
  23. impl Circle {
  24.     fn start(marble: Marble) -> Circle {
  25.         if marble != 0 { panic!("tried to start with a marble other than 0"); }
  26.         Circle {
  27.             vec: vec![marble],
  28.             current_i: 0,
  29.         }
  30.     }
  31.  
  32.     fn current(&self) -> &Marble {
  33.         &self.vec[self.current_i]
  34.     }
  35.  
  36.     fn place(&mut self, marble: Marble) {
  37.         if marble.is_scoring() { panic!("tried to place a marble that scores points"); }
  38.         let Self { vec, current_i } = self;
  39.         let i = (*current_i + 2) % vec.len();
  40.         if i == 0 || marble == 1 {
  41.             *current_i = vec.len();
  42.             vec.push(marble);
  43.         } else {
  44.             *current_i = i;
  45.             vec.insert(i, marble);
  46.         }
  47.     }
  48.  
  49.     fn score(&mut self, marble: Marble) -> u32 {
  50.         if !marble.is_scoring() { panic!("tried to score with a non-scoring marble"); }
  51.         let mut i_to_remove = self.current_i as isize - 7;
  52.         while i_to_remove < 0 { i_to_remove += self.vec.len() as isize; }
  53.         let i_to_remove = i_to_remove as usize;
  54.         let removed_marble: Marble = self.vec.remove(i_to_remove);
  55.         self.current_i = (i_to_remove + 1) % self.vec.len();
  56.         marble as u32 + removed_marble as u32
  57.     }
  58. }
  59.  
  60. fn fmt_secs(start: DateTime<Utc>) -> String {
  61.     format!("⏱ {}s", (Utc::now() - start).num_milliseconds() as f64 / 1000_f64)
  62. }
  63.  
  64. fn main() {
  65.     const NUM_PLAYERS: u32 = 9;
  66.     const LAST_MARBLE: Marble = 32;
  67.     // const NUM_PLAYERS: u32 = 455;
  68.     // const LAST_MARBLE: Marble = 71223;
  69.     let time = Utc::now();
  70.     println!("Part 1 high score: {} {}", part1(NUM_PLAYERS, LAST_MARBLE), fmt_secs(time));
  71. }
  72.  
  73. fn part1(num_players: u32, last_marble: Marble) -> u64 {
  74.     let mut player_scores = vec![0u64; num_players as usize];
  75.     let mut circle = Circle::start(0);
  76.     for i in 1u32.. {
  77.         let marble: Marble = i;
  78.         if marble.is_scoring() {
  79.             let score = circle.score(marble);
  80.             let player = (i % num_players) as usize;
  81.             player_scores[player] += score as u64;
  82.         } else {
  83.             circle.place(marble);
  84.         }
  85.         let visualization = circle.vec.iter().map(|marble| if marble == circle.current() {
  86.             format!("({}) ", marble.to_string())
  87.         } else {
  88.             format!("{} ", marble.to_string())
  89.         }).collect::<String>().trim().to_string();
  90.         println!("{}", visualization);
  91.         if marble == last_marble { break; }
  92.         if marble > last_marble { panic!("too many marbles"); }
  93.     }
  94.  
  95.     let (winner, high_score) = player_scores
  96.         .into_iter()
  97.         .enumerate()
  98.         .max_by(|(_, score1), (_, score2)| score1.cmp(score2)).unwrap();
  99.     println!("Winning elf: {}", winner);
  100.     high_score
  101. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement