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