Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extern crate chrono;
- use chrono::DateTime;
- use chrono::offset::Utc;
- type Marble = u32;
- trait MarbleTrait {
- fn is_scoring(&self) -> bool;
- }
- impl MarbleTrait for Marble {
- fn is_scoring(&self) -> bool {
- self % 23 == 0
- }
- }
- struct Circle {
- vec: Vec<Marble>,
- current_i: usize,
- }
- impl Circle {
- fn start(marble: Marble) -> Circle {
- if marble != 0 { panic!("tried to start with a marble other than 0"); }
- Circle {
- vec: vec![marble],
- current_i: 0,
- }
- }
- fn current(&self) -> &Marble {
- &self.vec[self.current_i]
- }
- fn place(&mut self, marble: Marble) {
- if marble.is_scoring() { panic!("tried to place a marble that scores points"); }
- let Self { vec, current_i } = self;
- let i = (*current_i + 2) % vec.len();
- if i == 0 || marble == 1 {
- *current_i = vec.len();
- vec.push(marble);
- } else {
- *current_i = i;
- vec.insert(i, marble);
- }
- }
- fn score(&mut self, marble: Marble) -> u32 {
- if !marble.is_scoring() { panic!("tried to score with a non-scoring marble"); }
- let mut i_to_remove = self.current_i as isize - 7;
- while i_to_remove < 0 { i_to_remove += self.vec.len() as isize; }
- let i_to_remove = i_to_remove as usize;
- let removed_marble: Marble = self.vec.remove(i_to_remove);
- self.current_i = (i_to_remove + 1) % self.vec.len();
- marble as u32 + removed_marble as u32
- }
- }
- fn fmt_secs(start: DateTime<Utc>) -> String {
- format!("⏱ {}s", (Utc::now() - start).num_milliseconds() as f64 / 1000_f64)
- }
- fn main() {
- const NUM_PLAYERS: u32 = 9;
- const LAST_MARBLE: Marble = 32;
- // const NUM_PLAYERS: u32 = 455;
- // const LAST_MARBLE: Marble = 71223;
- let time = Utc::now();
- println!("Part 1 high score: {} {}", part1(NUM_PLAYERS, LAST_MARBLE), fmt_secs(time));
- }
- fn part1(num_players: u32, last_marble: Marble) -> u64 {
- let mut player_scores = vec![0u64; num_players as usize];
- let mut circle = Circle::start(0);
- for i in 1u32.. {
- let marble: Marble = i;
- if marble.is_scoring() {
- let score = circle.score(marble);
- let player = (i % num_players) as usize;
- player_scores[player] += score as u64;
- } else {
- circle.place(marble);
- }
- let visualization = circle.vec.iter().map(|marble| if marble == circle.current() {
- format!("({}) ", marble.to_string())
- } else {
- format!("{} ", marble.to_string())
- }).collect::<String>().trim().to_string();
- println!("{}", visualization);
- if marble == last_marble { break; }
- if marble > last_marble { panic!("too many marbles"); }
- }
- let (winner, high_score) = player_scores
- .into_iter()
- .enumerate()
- .max_by(|(_, score1), (_, score2)| score1.cmp(score2)).unwrap();
- println!("Winning elf: {}", winner);
- high_score
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement