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