diff --git a/2018/Cargo.toml b/2018/Cargo.toml index c86bbc0..ce108d6 100644 --- a/2018/Cargo.toml +++ b/2018/Cargo.toml @@ -9,3 +9,4 @@ clap = "2.32" regex = "1.1.0" chrono = "0.4.6" itertools = "0.7.11" +intrusive-collections = "0.7.8" diff --git a/2018/src/day09.rs b/2018/src/day09.rs index cb19f8a..3b3734a 100644 --- a/2018/src/day09.rs +++ b/2018/src/day09.rs @@ -1,30 +1,53 @@ -use common::Solution; +use std::cell::Cell; use std::io::Read; +use intrusive_collections::{LinkedList, LinkedListLink}; + +use common::Solution; + +struct Marble { + link: LinkedListLink, + value: Cell, +} + +impl Marble { + pub fn new(value: usize) -> Box { + Box::new(Marble { + link: LinkedListLink::new(), + value: Cell::new(value), + }) + } +} + +intrusive_adapter!(MarbleAdapter = Box: Marble { link: LinkedListLink }); + fn winning_marbles(elves: usize, marbles: usize) -> usize { let mut scores = vec![0usize; elves]; - let mut state = Vec::new(); - state.push(0); - let mut current = 0; + let mut state: LinkedList<_> = LinkedList::new(MarbleAdapter::new()); + state.push_front(Marble::new(0)); + let mut current = state.front_mut(); for marble in 1..=marbles { if marble % 23 == 0 { let player = marble % elves; - for _ in 0..7 {} - let to_remove = (current + state.len() - 7) % state.len(); - - scores[player] += marble + state[to_remove]; - - state.remove(to_remove); - current = to_remove; - } else { - let after = (current + 1) % state.len(); - if after == state.len() - 1 { - state.push(marble); - } else { - state.insert(after + 1, marble); + for _ in 0..7 { + current.move_prev(); + if current.is_null() { + current.move_prev(); + } } - current = after + 1; + + let to_remove = current.get().unwrap().value.get(); + + scores[player] += marble + to_remove; + current.remove(); + } else { + current.move_next(); + if current.is_null() { + current.move_next(); + } + current.insert_after(Marble::new(marble)); + current.move_next(); } } diff --git a/2018/src/lib.rs b/2018/src/lib.rs index 2c446d2..99d6cfc 100644 --- a/2018/src/lib.rs +++ b/2018/src/lib.rs @@ -1,4 +1,5 @@ extern crate chrono; +#[macro_use] extern crate intrusive_collections; #[macro_use] extern crate itertools; extern crate regex;