day 5: part 1 & 2: rust
This commit is contained in:
parent
72f4207e0f
commit
e2b0a51104
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "day05"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -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(())
|
||||||
|
}
|
Loading…
Reference in New Issue