day 5: part 1 & 2: rust

This commit is contained in:
Samuel Ortion 2024-12-10 12:02:29 +01:00
parent 72f4207e0f
commit e2b0a51104
Signed by: sortion
GPG Key ID: 9B02406F8C4FB765
2 changed files with 167 additions and 0 deletions

View File

@ -0,0 +1,6 @@
[package]
name = "day05"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,161 @@
use std::{cmp::Ordering, collections::{BTreeSet, HashMap}};
fn filter_orderings(orderings: &Vec<(u64, u64)>, update: &Vec<u64>) -> 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<Vec<bool>>) -> bool {
for u in 0..graph.len() {
if graph[u][v] {
return true;
}
}
return false;
}
fn has_edge(graph: &Vec<Vec<bool>>) -> 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<bool>>) -> Vec<usize> {
let mut graph = graph.clone();
let mut l: Vec<usize> = Vec::new();
let mut s: BTreeSet<usize> = 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<u64>, ordering: &Vec<u64>) -> 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<Vec<bool>>, HashMap<usize, u64>) {
let mut n: usize = 0;
let mut vertex_to_number: HashMap<usize, u64> = HashMap::new();
let mut number_to_vertex: HashMap<u64, usize> = 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<bool>> = 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>) -> u64 {
let index = array.len() / 2;
array[index]
}
fn compare_ordering(a: u64, b: u64, order: &Vec<u64>) -> 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<u64>> = 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::<u64>().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(())
}