[2018][rust][09]
change uzoprwmntqrvxqxwzvyzykryqmrylvuk
commit 6d94b429807ad2e423901a9e9ef1bd4a57942b45
author Alpha Chen <alpha.chen@gmail.com>
date
parent tyvwxxyx
diff --git a/2018/rust/src/bin/day_09.rs b/2018/rust/src/bin/day_09.rs
new file mode 100644
index 0000000..c41514e
--- /dev/null
+++ b/2018/rust/src/bin/day_09.rs
@@ -0,0 +1,90 @@
+use std::error::Error;
+
+use regex::Regex;
+
+use advent_of_code::main;
+
+main!();
+
+fn solve(input: &str) -> Result<String, Box<Error>> {
+    let re = Regex::new(r"(?P<players>\d+) players; last marble is worth (?P<points>\d+) points").unwrap();
+    let caps = re.captures(input).unwrap();
+    let player_count = caps.name("players").unwrap().as_str().parse()?;
+    let marble_count: usize = caps.name("points").unwrap().as_str().parse()?;
+    let high_score = play(player_count, marble_count * 100);
+    Ok(high_score.to_string())
+}
+
+fn play(player_count: usize, marble_count: usize) -> usize {
+    let mut scores = vec![0; player_count];
+    let mut circle = vec![Marble{value: 0, next: 0, prev: 0}];
+
+    let mut current_player = 0;
+    let mut current_index: usize = 0;
+
+    for value in 1..=marble_count {
+        if value % 23 == 0 {
+            scores[current_player] += value;
+            for _ in 0..7 {
+                current_index = circle[current_index].prev;
+            }
+            let marble = &circle[current_index];
+            scores[current_player] += marble.value;
+            let prev = marble.prev;
+            let next = marble.next;
+            circle[prev].next = next;
+            circle[next].prev = prev;
+            current_index = next;
+        } else {
+            current_index = circle[current_index].next;
+            let current_marble = &circle[current_index];
+            let next = current_marble.next;
+            let prev = current_index;
+            let marble = Marble{value, next, prev};
+            circle.push(marble);
+            current_index = circle.len() - 1;
+            circle[prev].next = current_index;
+            circle[next].prev = current_index;
+        }
+
+        // if current_index % 100000 == 0 {
+        //     println!("{}", current_index);
+        // }
+        // println!("[{}] {:?}", current_player + 1, circle_to_string(&circle));
+
+        current_player += 1;
+        current_player %= player_count;
+    }
+
+    *scores.iter().max().unwrap()
+}
+
+#[test]
+fn test_play() {
+    assert_eq!(play(9, 25), 32);
+    // assert_eq!(play(10, 1618), 8317);
+    assert_eq!(play(13, 7999), 146373);
+    // assert_eq!(play(17, 1104), 2764);
+    // assert_eq!(play(21, 6111), 54718);
+    // assert_eq!(play(30, 5807), 37305);
+}
+
+// fn circle_to_string(circle: &Vec<Marble>) -> String {
+//     let mut i = 0;
+//     let mut v = Vec::new();
+//     loop {
+//         v.push(circle[i].value);
+//         i = circle[i].next;
+//         if i == 0 {
+//             break;
+//         }
+//     }
+//     format!("{:?}", v)
+// }
+
+#[derive(Debug)]
+struct Marble {
+    value: usize,
+    next: usize,
+    prev: usize,
+}