Day 5
This commit is contained in:
parent
6674696505
commit
1e0bcb0c39
1 changed files with 157 additions and 0 deletions
157
src/bin/day5.rs
Normal file
157
src/bin/day5.rs
Normal 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(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue