From 91ac0a0688eb2dce6d2b2a176d26805f2f153067 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Leon=20Gr=C3=BCnewald?= <leon@doggoat.de>
Date: Thu, 12 Dec 2024 02:48:10 +0100
Subject: [PATCH] Finish challenge 5

---
 5/.gitignore  |  1 +
 5/Cargo.lock  | 16 ++++++++++
 5/Cargo.toml  |  7 +++++
 5/src/main.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+)
 create mode 100644 5/.gitignore
 create mode 100644 5/Cargo.lock
 create mode 100644 5/Cargo.toml
 create mode 100644 5/src/main.rs

diff --git a/5/.gitignore b/5/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/5/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/5/Cargo.lock b/5/Cargo.lock
new file mode 100644
index 0000000..c3ab706
--- /dev/null
+++ b/5/Cargo.lock
@@ -0,0 +1,16 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anyhow"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
+
+[[package]]
+name = "aoc24-5"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+]
diff --git a/5/Cargo.toml b/5/Cargo.toml
new file mode 100644
index 0000000..4ae52c8
--- /dev/null
+++ b/5/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "aoc24-5"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0"
diff --git a/5/src/main.rs b/5/src/main.rs
new file mode 100644
index 0000000..254a9e3
--- /dev/null
+++ b/5/src/main.rs
@@ -0,0 +1,84 @@
+use std::fs::OpenOptions;
+use std::io::Read;
+use anyhow::bail;
+
+fn get_data() -> anyhow::Result<String> {
+    let args = std::env::args();
+
+    // First argument is the executable, second argument is the path to our input.
+    if args.len() < 2 { bail!("Not enough arguments") }
+
+    let mut data = String::new();
+    {
+        let mut file = OpenOptions::new().read(true).open(args.last().expect("No file path"))?;
+        file.read_to_string(&mut data)?;
+    }
+    Ok(data)
+}
+
+fn parse_rules_and_updates(data: &String) -> (Vec<(&str, &str)>, Vec<Vec<&str>>){
+    let (rules, mut rest): (Vec<&str>, _) = data.lines()
+        .partition(|line| line.contains("|"));
+
+    let rules: Vec<(&str, &str)> = rules.into_iter()
+        .map(|rule| rule.split_once("|").expect("Could not split"))
+        .collect();
+
+    rest.drain(0..1);
+
+    let updates: Vec<Vec<&str>> = rest.into_iter()
+        .map(|page| page.split(",").collect())
+        .collect();
+
+    (rules, updates)
+}
+
+fn check_rule_compliance(update: &Vec<&str>, rule: &(&str, &str)) -> Option<(usize, usize)> {
+    let before_index_opt = update.iter().position(|elem| {*elem == rule.0});
+    let after_index_opt = update.iter().position(|elem| {*elem == rule.1});
+
+    match (before_index_opt, after_index_opt) {
+        (Some(before_index), Some(after_index)) => {
+            if before_index > after_index {
+                return Some((before_index, after_index));
+            }
+        }
+        _ => {
+            // println!("Skipping rule {rule:?}");
+        }
+    }
+    None
+}
+
+fn sum_middle_page_nums(updates: Vec<Vec<&str>>) -> i64 {
+    updates.iter()
+        .map(|update| update[update.len()/2])
+        .map(|middle| middle.parse::<i64>().unwrap())
+        .sum()
+}
+
+fn main() -> anyhow::Result<()> {
+    let data = get_data()?;
+    let (rules, updates) = parse_rules_and_updates(&data);
+    let mut correct_updates = Vec::new();
+
+    'update: for update in updates {
+        for rule in &rules {
+            if let Some(_) = check_rule_compliance(&update, rule) {
+                /*println!(
+                    "Rule issue: {:?} ({before_index:?}) {:?} ({after_index:?})",
+                    update[before_index],
+                    update[after_index]
+                );
+                println!("Elements: {update:?}");*/
+                continue 'update;
+            }
+        }
+        correct_updates.push(update);
+    }
+    
+    println!("{}", sum_middle_page_nums(correct_updates));
+    Ok(())
+}
+
+