From e2b0a511040509b36f73ed3338772f87460f77ca Mon Sep 17 00:00:00 2001 From: Samuel Ortion Date: Tue, 10 Dec 2024 12:02:29 +0100 Subject: [PATCH] day 5: part 1 & 2: rust --- 2024/days/05/day05/Cargo.toml | 6 ++ 2024/days/05/day05/src/main.rs | 161 +++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 2024/days/05/day05/Cargo.toml create mode 100644 2024/days/05/day05/src/main.rs diff --git a/2024/days/05/day05/Cargo.toml b/2024/days/05/day05/Cargo.toml new file mode 100644 index 0000000..9ff168e --- /dev/null +++ b/2024/days/05/day05/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day05" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/2024/days/05/day05/src/main.rs b/2024/days/05/day05/src/main.rs new file mode 100644 index 0000000..8e3e896 --- /dev/null +++ b/2024/days/05/day05/src/main.rs @@ -0,0 +1,161 @@ +use std::{cmp::Ordering, collections::{BTreeSet, HashMap}}; + +fn filter_orderings(orderings: &Vec<(u64, u64)>, update: &Vec) -> Vec<(u64, u64)> { + let mut new_orderings: Vec<(u64, u64)> = Vec::new(); + for item in orderings { + if update.contains(&item.0) && update.contains(&item.1) { + new_orderings.push(*item); + } + } + new_orderings +} + +fn has_incoming(v: usize, graph: &Vec>) -> bool { + for u in 0..graph.len() { + if graph[u][v] { + return true; + } + } + return false; +} + +fn has_edge(graph: &Vec>) -> bool { + for i in 0..graph.len() { + for j in 0..graph[i].len() { + if graph[i][j] { + return true; + } + } + } + return false; +} + +fn topological_sorting(graph: &Vec>) -> Vec { + let mut graph = graph.clone(); + let mut l: Vec = Vec::new(); + let mut s: BTreeSet = BTreeSet::new(); + // Extract the set of nodes with no incoming edge + for v in 0..graph.len() { + if !has_incoming(v, &graph) { + s.insert(v); + } + } + while !s.is_empty() { + let u: usize = s.pop_first().unwrap(); + l.push(u); + for v in 0..graph.len() { + if graph[u][v] { + graph[u][v] = false; + if !has_incoming(v, &graph) { + s.insert(v); + } + } + } + } + if has_edge(&graph) { + panic!("Graph has at least one cycle"); + } + l +} + +fn is_correct(update: &Vec, ordering: &Vec) -> bool { + + for i in 0..(update.len() - 1) { + let u = update[i]; + let ordering_i = ordering.iter().position(|&e| e == u).unwrap(); + for j in (i+1)..update.len() { + let v = update[j]; + let ordering_j = ordering.iter().position(|&e| e == v).unwrap(); + if ordering_i > ordering_j { + return false; + } + } + } + return true; +} + +fn parse_graph(ordering: &Vec<(u64, u64)>) -> (Vec>, HashMap) { + let mut n: usize = 0; + let mut vertex_to_number: HashMap = HashMap::new(); + let mut number_to_vertex: HashMap = HashMap::new(); + for order in ordering { + let u = order.0; + let v = order.1; + if !number_to_vertex.contains_key(&u) { + number_to_vertex.insert(u, n); + vertex_to_number.insert(n, u); + n += 1; + } + if !number_to_vertex.contains_key(&v) { + number_to_vertex.insert(v, n); + vertex_to_number.insert(n, v); + n += 1; + } + } + let mut graph: Vec> = vec![vec![false; n]; n]; + for order in ordering { + let u = *number_to_vertex.get(&order.0).unwrap(); + let v = *number_to_vertex.get(&order.1).unwrap(); + graph[u][v] = true; + } + (graph, vertex_to_number) +} + +fn get_middle(array: &Vec) -> u64 { + let index = array.len() / 2; + array[index] +} + +fn compare_ordering(a: u64, b: u64, order: &Vec) -> Ordering { + let i = order.iter().position(|&e| e == a); + let j = order.iter().position(|&e| e == b); + return i.cmp(&j); +} + +fn main() -> std::io::Result<()> { + let mut sum_ordered: u64 = 0; + let mut sum_unordered: u64 = 0; + let mut orderings: Vec<(u64, u64)> = Vec::new(); + let mut updates: Vec> = Vec::new(); + let mut part = 0; + for line in std::io::stdin().lines() { + let line = line.unwrap(); + if line == "" { + part += 1; + } else if part == 0 { + let mut parts = line.split("|"); + let ordering_first = parts.next().unwrap(); + let ordering_second = parts.next().unwrap(); + let ordering_first: u64 = ordering_first.parse().unwrap(); + let ordering_second: u64 = ordering_second.parse().unwrap(); + let ordering = (ordering_first, ordering_second); + orderings.push(ordering); + } else if part == 1 { + let parts = line.split(","); + let update = parts.map(|num| num.parse::().unwrap()).collect(); + updates.push(update); + } + } + + for update in updates { + let update_orderings = filter_orderings(&orderings, &update); + let (graph, vertex_to_number) = parse_graph(&update_orderings); + let topological_sort = topological_sorting(&graph); + let sorted_num = topological_sort + .iter() + .map(|v| *vertex_to_number.get(v).unwrap()) + .collect(); + if is_correct(&update, &sorted_num) { + let middle = get_middle(&update); + sum_ordered += middle; + } else { + let mut update_sorted = update.clone(); + update_sorted.sort_by(|a, b| compare_ordering(*a, *b, &sorted_num)); + let middle = get_middle(&update_sorted); + sum_unordered += middle; + } + } + println!("{}", sum_ordered); + println!("{}", sum_unordered); + Ok(()) +}