This commit is contained in:
traxys 2024-12-05 11:27:51 +01:00
parent 6674696505
commit 1e0bcb0c39

157
src/bin/day5.rs Normal file
View file

@ -0,0 +1,157 @@
use std::{collections::HashMap, time::Instant};
use aoc_2024::{load, print_res};
use bstr::BString;
use color_eyre::eyre::Context;
#[derive(Debug)]
pub struct PageGraph {
successors: HashMap<usize, Vec<usize>>,
predecesors: HashMap<usize, Vec<usize>>,
}
type Parsed = (PageGraph, Vec<Vec<usize>>);
#[inline(never)]
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
let input = core::str::from_utf8(input)?;
let mut graph = PageGraph {
successors: HashMap::new(),
predecesors: HashMap::new(),
};
let Some((succesors, sequences)) = input.split_once("\n\n") else {
color_eyre::eyre::bail!("Missing '\\n\\n'");
};
for succesor in succesors.lines() {
let Some((first, second)) = succesor.split_once('|') else {
color_eyre::eyre::bail!("Missing '|' in '{succesor}'");
};
let first: usize = first
.parse()
.with_context(|| format!("Could not parse first ({first})"))?;
let second: usize = second
.parse()
.with_context(|| format!("Could not parse second ({second})"))?;
graph.successors.entry(first).or_default().push(second);
graph.predecesors.entry(second).or_default().push(first);
}
let sequences = sequences
.lines()
.map(|seq| {
seq.split(',')
.map(|n| n.parse::<usize>())
.collect::<Result<Vec<_>, _>>()
})
.collect::<Result<Vec<_>, _>>()?;
Ok((graph, sequences))
}
#[inline(never)]
pub fn part1((graph, sequences): Parsed) {
let mut sum = 0;
'seq: for seq in sequences {
let mut seen = Vec::new();
for n in &seq {
seen.push(n);
if graph
.successors
.get(n)
.map(|x| -> &[_] { x })
.unwrap_or_else(|| &[])
.iter()
.any(|s| seen.contains(&s))
{
continue 'seq;
}
}
sum += seq[seq.len() / 2];
}
print_res!("Sum of middle pages: {sum}");
}
impl PageGraph {
fn reorder_sequence(&self, seq: &mut [usize]) {
seq.sort_by(|a, b| {
let pred_a = self.predecesors.get(a);
let pred_b = self.predecesors.get(b);
if a == b {
return std::cmp::Ordering::Equal;
}
if let Some(pa) = pred_a {
if pa.contains(b) {
return std::cmp::Ordering::Greater;
}
}
if let Some(pb) = pred_b {
if pb.contains(a) {
return std::cmp::Ordering::Less;
}
}
panic!("No predecessor found");
});
}
}
#[inline(never)]
pub fn part2((graph, sequences): Parsed) {
let mut sum = 0;
'seq: for mut seq in sequences {
let mut seen = Vec::new();
for n in &seq {
seen.push(n);
if graph
.successors
.get(n)
.map(|x| -> &[_] { x })
.unwrap_or_else(|| &[])
.iter()
.any(|s| seen.contains(&s))
{
graph.reorder_sequence(&mut seq);
sum += seq[seq.len() / 2];
continue 'seq;
}
}
}
print_res!("Sum of incorrect middle pages: {sum}");
}
pub fn main() -> color_eyre::Result<()> {
let context = load()?;
let start = Instant::now();
let parsed = parsing(&context.input)?;
let elapsed = humantime::format_duration(start.elapsed());
let start = Instant::now();
if context.part == 1 {
part1(parsed);
} else {
part2(parsed);
}
let elapsed_part = humantime::format_duration(start.elapsed());
println!(" Parsing: {elapsed}");
println!(" Solving: {elapsed_part}");
Ok(())
}