DEV Community

Discussion on: AoC Day 9: Marble Mania

Collapse
 
rpalo profile image
Ryan Palo

I found out (seems like a lot of other people did too) that rotating a doubly-linked list is way faster than inserting/removing with indices. Still felt like a boss when my code cranked through seven million possibilities in a few seconds :) Man, I love coding.

/// Day 9: Marble Mania
/// 
/// Figure out the scores of elves playing marbles

use std::collections::VecDeque;

/// Calculate what the highest player's score is
pub fn winning_score(number_of_players: usize, max_points: usize) -> usize {
    let mut marbles: VecDeque<usize> = VecDeque::new();
    let mut players: Vec<usize> = Vec::new();
    for _i in 0..number_of_players {
        players.push(0);
    }

    marbles.push_back(0);
    marbles.push_back(1);

    for i in 2..=max_points {
        if i % 100000 == 0 { println!("{}", i) };  // Speed testing feedback

        if i % 23 == 0 {
            players[i % number_of_players] += i;
            rotate_right(&mut marbles, 7);
            players[i % number_of_players] += marbles.pop_back().unwrap();
            rotate_left(&mut marbles, 1);
        } else {
            rotate_left(&mut marbles, 1);
            marbles.push_back(i);
        }
    }

    *players.iter().max().unwrap()
}

fn rotate_right(list: &mut VecDeque<usize>, times: usize) {
    for _i in 0..times {
        let value = list.pop_back().expect("Empty VecDeque");
        list.push_front(value);
    }
}

fn rotate_left(list: &mut VecDeque<usize>, times: usize) {
    for _i in 0..times {
        let value = list.pop_front().expect("Empty VecDeque");
        list.push_back(value);
    }
}