diff --git a/2024/day05/input_small.txt b/2024/day05/input_small.txt index e69de29..9d146d6 100644 --- a/2024/day05/input_small.txt +++ b/2024/day05/input_small.txt @@ -0,0 +1,28 @@ +47|53 +97|13 +97|61 +97|47 +75|29 +61|13 +75|53 +29|13 +97|29 +53|29 +61|53 +97|53 +61|29 +47|13 +75|47 +97|75 +47|61 +75|61 +47|29 +75|13 +53|13 + +75,47,61,53,29 +97,61,53,29,13 +75,29,13 +75,97,47,61,53 +61,13,29 +97,13,75,29,47 diff --git a/2024/day05/src/lib.rs b/2024/day05/src/lib.rs index 2000265..7dbfaa9 100644 --- a/2024/day05/src/lib.rs +++ b/2024/day05/src/lib.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use helper::{parse_unwrap, Day, IteratorExt, Variants}; pub fn main() { @@ -46,7 +48,99 @@ fn part1(input: &str) -> u64 { updates.push(numbers); } - 0 + fn build_nodes( + rules: impl Iterator, + ) -> (HashMap, Vec, Vec>) { + let mut nodes_lookup = HashMap::new(); + let mut nodes = Vec::new(); + let mut edges = Vec::>::new(); + for (first, then) in rules { + let first = *nodes_lookup.entry(first).or_insert_with(|| { + nodes.push(first); + edges.push(Vec::new()); + nodes.len() - 1 + }); + let then = *nodes_lookup.entry(then).or_insert_with(|| { + nodes.push(then); + edges.push(Vec::new()); + nodes.len() - 1 + }); + if !edges[first].contains(&then) { + edges[first].push(then); + } + } + + assert_eq!(nodes_lookup.len(), nodes.len()); + assert_eq!(nodes.len(), edges.len()); + (nodes_lookup, nodes, edges) + } + + /* + let mut all_sorted = Vec::new(); + let mut marked = vec![false; nodes.len()]; + let mut worklist = VecDeque::new(); + + while let Some((i, _)) = marked + .iter() + .enumerate() + .find(|(_, is_marked)| !**is_marked) + { + let mut temporary_ordering = Vec::new(); + worklist.clear(); + worklist.push_back(i); + + while let Some(item) = worklist.pop_front() { + if marked[item] { + continue; + } + temporary_ordering.push(nodes[item]); + for child in edges[item].iter().rev() { + worklist.push_front(*child); + } + marked[item] = true; + } + + all_sorted.extend_from_slice(&temporary_ordering); + } + + dbg!(all_sorted); + */ + + fn must_be_before(edges: &[Vec], nodes: &[u64], before: usize, after: usize) -> bool { + if edges[before].contains(&after) { + return true; + } + for &child in &edges[before] { + if must_be_before(edges, nodes, child, after) { + return true; + } + } + false + } + + let mut result = 0; + for update in updates { + let (nodes_lookup, nodes, edges) = build_nodes( + rules + .iter() + .filter(|(a, b)| update.contains(&a) && update.contains(&b)) + .copied(), + ); + + let mut is_bad = false; + for ab in update.windows(2) { + let (a, b) = (ab[0], ab[1]); + if must_be_before(&edges, &nodes, nodes_lookup[&b], nodes_lookup[&a]) { + is_bad = true; + break; + } + } + if !is_bad { + result += update[update.len() / 2]; + } + } + + result } fn part2(_input: &str) -> u64 { @@ -57,7 +151,7 @@ helper::tests! { day05 Day05; part1 { small => 143; - default => 0; + default => 4959; } part2 { small => 0;