This commit is contained in:
nora 2024-12-07 12:19:30 +01:00
parent d23c534f5d
commit c4518496d3

View file

@ -1,3 +1,5 @@
use std::collections::VecDeque;
use helper::{parse_unwrap, Day, IteratorExt, Variants}; use helper::{parse_unwrap, Day, IteratorExt, Variants};
pub fn main() { pub fn main() {
@ -12,7 +14,7 @@ helper::define_variants! {
basic => crate::part1, sample_count=1000; basic => crate::part1, sample_count=1000;
} }
part2 { part2 {
basic => crate::part2; basic => crate::part2, sample_count=1000;
} }
} }
@ -124,8 +126,98 @@ fn part1(input: &str) -> u64 {
result result
} }
fn part2(_input: &str) -> u64 { fn part2(input: &str) -> u64 {
0 struct Update {
values: Vec<u64>,
set: [bool; 100],
}
let mut rules = Vec::new();
let mut updates = Vec::new();
let mut lines = input.lines();
while let Some(line) = lines.next() {
if line.is_empty() {
break;
}
let values = line
.split('|')
.collect_array::<2>()
.unwrap()
.map(parse_unwrap);
rules.push((values[0], values[1]));
}
while let Some(line) = lines.next() {
let values = line.split(",").map(parse_unwrap).collect::<Vec<_>>();
let mut set = [false; 100];
for value in &values {
set[*value as usize] = true;
}
updates.push(Update { values, set });
}
fn build_nodes(edges: &mut Vec<[bool; 100]>, rules: impl Iterator<Item = (u64, u64)>) {
edges.clear();
edges.resize(100, [false; 100]);
for (first, then) in rules {
edges[first as usize][then as usize] = true;
}
}
let mut edges = Vec::new();
let mut result = 0;
for update in updates {
build_nodes(
&mut edges,
rules
.iter()
.filter(|(a, b)| update.set[*a as usize] && update.set[*b as usize])
.copied(),
);
let mut is_bad = false;
for ab in update.values.windows(2) {
let (a, b) = (ab[0], ab[1]);
if edges[b as usize][a as usize] {
is_bad = true;
break;
}
}
if is_bad {
// do Topological sort:
// https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
let mut all_sorted = VecDeque::new();
let mut marked = [false; 100];
fn visit(
all_sorted: &mut VecDeque<u64>,
marked: &mut [bool; 100],
edges: &[[bool; 100]],
node: usize,
) {
if marked[node] {
return;
}
for (child, _) in edges[node].iter().enumerate().filter(|(_, edge)| **edge) {
visit(all_sorted, marked, edges, child);
}
marked[node] = true;
all_sorted.push_front(node as u64);
}
while let Some(next) = update.values.iter().find(|value| !marked[**value as usize]) {
visit(&mut all_sorted, &mut marked, &edges, *next as usize);
}
result += all_sorted[all_sorted.len() / 2];
}
}
result
} }
helper::tests! { helper::tests! {
@ -135,8 +227,8 @@ helper::tests! {
default => 4959; default => 4959;
} }
part2 { part2 {
small => 0; small => 123;
default => 0; default => 4655;
} }
} }
helper::benchmarks! {} helper::benchmarks! {}