summaryrefslogtreecommitdiffstats
path: root/day9/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'day9/src/main.rs')
-rw-r--r--day9/src/main.rs149
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