diff --git a/2024/day5/.gitignore b/2024/day5/.gitignore new file mode 100644 index 0000000..2ac37a0 --- /dev/null +++ b/2024/day5/.gitignore @@ -0,0 +1,2 @@ +target +input.txt diff --git a/2024/day5/Cargo.lock b/2024/day5/Cargo.lock new file mode 100644 index 0000000..7a62bb0 --- /dev/null +++ b/2024/day5/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day5" +version = "0.1.0" diff --git a/2024/day5/Cargo.toml b/2024/day5/Cargo.toml new file mode 100644 index 0000000..49bdb49 --- /dev/null +++ b/2024/day5/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day5" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/2024/day5/src/main.rs b/2024/day5/src/main.rs new file mode 100644 index 0000000..f1f7b26 --- /dev/null +++ b/2024/day5/src/main.rs @@ -0,0 +1,70 @@ +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::fs; +use std::time::Instant; + +fn main() { + let input = fs::read_to_string("input.txt").expect("Failed to read input file"); + let (rules_str, updates_str) = input.split_once("\n\n").unwrap(); + + let rules: Vec<&str> = rules_str.split_whitespace().collect::>(); + let updates: Vec<&str> = updates_str.split_whitespace().collect::>(); + + let mut table: HashMap<&str, Vec<&str>> = HashMap::new(); + for r in rules { + let parts = r.split('|').collect::>(); + if parts.len() == 2 { + table.entry(parts[0]).or_default().push(parts[1]); + } + } + + let start = Instant::now(); + let (solution1, solution2) = puzzle1_2(&updates, &table); + let end = Instant::now() - start; + + println!("Solution 1: {}", solution1); + println!("Solution 2: {}", solution2); + println!("Time: {}", end.as_micros()); +} + +fn puzzle1_2(updates: &[&str], table: &HashMap<&str, Vec<&str>>) -> (i32, i32) { + let mut counter1 = 0; + let mut counter2 = 0; + + for update in updates { + let ud = update.split(',').collect::>(); + + let mut repair = false; + for (i, u) in ud.iter().enumerate() { + if let Some(dependencies) = table.get(*u) { + if dependencies.iter().any(|k| ud[..i].contains(k)) { + counter2 += repair_update(&ud, table); + repair = true; + break; + } + } + } + if !repair { + counter1 += ud[ud.len() / 2].parse::().unwrap_or(0); + } + } + (counter1, counter2) +} + +fn repair_update(ud: &[&str], table: &HashMap<&str, Vec<&str>>) -> i32 { + let mut new_ud = Vec::new(); + + for u in ud { + let mut counter = new_ud.len(); + while let Some(dependencies) = table.get(u) { + if dependencies.iter().any(|k| new_ud[..counter].contains(k)) { + counter -= 1; + } else { + break; + } + } + new_ud.insert(counter, u); + } + + new_ud[new_ud.len() / 2].parse::().unwrap_or(0) +}