diff options
| author | Jan Tuomi <jan.tuomi@eficode.com> | 2018-12-10 15:44:07 +0200 |
|---|---|---|
| committer | Jan Tuomi <jan.tuomi@eficode.com> | 2018-12-10 15:44:07 +0200 |
| commit | b8e9c88da10835a32c82891c93023eb6eda952ed (patch) | |
| tree | cf5ebb2980f8fb755960453f54844d69cd14f865 /day9/src | |
| parent | 8467faf37f2142bd48570aa6bff3ee685ac205ce (diff) | |
Solve day9
Diffstat (limited to 'day9/src')
| -rw-r--r-- | day9/src/main.rs | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/day9/src/main.rs b/day9/src/main.rs new file mode 100644 index 0000000..49d89ad --- /dev/null +++ b/day9/src/main.rs @@ -0,0 +1,149 @@ +use std::env; +use std::io::BufReader; +use std::io::BufRead; +use std::fs::File; +use std::process; + +// extern crate flame; +#[macro_use] extern crate text_io; + +type Marble = u32; + +struct Circle { + marbles: Vec<Marble>, + current_i: i32, + n: i32 +} + +impl Circle { + fn get(&self, pos: i32) -> (i32, Marble) { + // let _guard = flame::start_guard("get"); + let n = self.marbles.len() as i32; + let i = (pos % n + n) % n; + (i, self.marbles[i as usize]) + } + + fn set_current(&mut self, pos: i32) { + // let _guard = flame::start_guard("set_current"); + let i = (pos % self.n + self.n) % self.n; + self.current_i = i; + } + + fn get_current(&self) -> (i32, Marble) { + // let _guard = flame::start_guard("get_current"); + let cur = self.marbles[self.current_i as usize]; + + (self.current_i, cur) + } + + fn go_around(&self, delta: i32) -> (i32, Marble) { + // let _guard = flame::start_guard("go_around"); + self.get(self.current_i as i32 + delta) + } + + fn clockwise(&mut self, delta: i32) -> (i32, Marble) { + // let _guard = flame::start_guard("clockwise"); + self.go_around(delta) + } + + fn counterclockwise(&mut self, delta: i32) -> (i32, Marble) { + // let _guard = flame::start_guard("counterclockwise"); + self.go_around(-delta) + } + + fn insert(&mut self, pos: i32, marble: Marble) { + // let _guard = flame::start_guard("insert"); + let i = (pos % self.n + self.n) % self.n + 1; + self.marbles.insert(i as usize, marble); + self.n += 1; + } + + fn remove(&mut self, pos: i32) { + // let _guard = flame::start_guard("remove"); + let (i, m) = self.get(pos); + let (_cur_i, cur) = self.get_current(); + if m == cur { + panic!("Removed current marble!"); + } + + self.marbles.remove(i as usize); + self.n -= 1; + } +} + +fn build_circle() -> Circle { + // let _guard = flame::start_guard("build_circle"); + let init_marbles: Vec<Marble> = vec![0; 1]; + let circle = Circle { marbles: init_marbles, current_i: 0, n: 1 }; + circle +} + +fn print_state(circle: &Circle, turn: usize) { + print!("[{}] ", turn); + for marble in &circle.marbles { + let (_cur_i, cur) = circle.get_current(); + if &cur == marble { + print!(" ({}) ", marble); + } else { + print!(" {} ", marble); + } + } + print!("\n") +} + +fn main() { + let args: Vec<String> = env::args().collect(); + if args.len() != 2 { + println!("Wrong number of arguments. Provide a file name and worker count."); + process::exit(1); + } + let filename = &args[1]; + + println!("Using file {} as input.", filename); + let f = match File::open(filename) { + Ok(file) => file, + Err(e) => { + println!("Failed to open file {}. {:?}", filename, e); + process::exit(1); + } + }; + let file = BufReader::new(&f); + let lines: Vec<String> = file.lines() + .map(|line| line.expect("Could not parse line.")) + .collect(); + + assert_eq!(lines.len(), 1); + + let line = &lines[0]; + let (player_count, marble_count): (usize, usize); + scan!(line.bytes() => "{} players; last marble is worth {} points", player_count, marble_count); + + let mut scores: Vec<u32> = vec![0; player_count]; + let mut circle = build_circle(); + let mut turn: usize = 0; + for marble in 1..(marble_count + 1) as Marble { + if marble % 23 == 0 { + scores[turn] += marble; + let (rem_i, rem_m): (i32, Marble) = circle.counterclockwise(7); + circle.remove(rem_i); + scores[turn] += rem_m; + let (new_cur_i, _new_cur) = circle.get(rem_i as i32); + circle.set_current(new_cur_i); + } else { + let (clockwise_i, _clockwise_m) = circle.clockwise(1); + circle.insert(clockwise_i, marble); + circle.set_current(clockwise_i + 1); + } + + // print_state(&circle, turn + 1); + if marble % 1000 == 0 { + let progress = 100.0 * (marble as f32) / marble_count as f32; + println!("Debug: Progress: {} %, Processed {} / {}", progress, marble, marble_count); + } + turn = (turn + 1) % player_count; + } + + let max_score: &u32 = scores.iter().max().expect("No scores in vector"); + println!("Max score: {}", max_score); + // flame::dump_html(&mut File::create("flame-graph.html").unwrap()).unwrap(); +}
\ No newline at end of file |
