This commit is contained in:
Quentin Boyer 2025-12-07 11:07:37 +01:00
parent 36008a5622
commit 47c7362687
2 changed files with 128 additions and 0 deletions

120
src/bin/day7.rs Normal file
View file

@ -0,0 +1,120 @@
use std::time::Instant;
use aoc_2025::{Grid, load, print_res};
use bstr::{BString, ByteSlice};
use color_eyre::eyre::ContextCompat;
#[derive(PartialEq, Eq, Debug)]
pub enum ManifoldEntry {
Start,
Empty,
Splitter,
}
impl std::fmt::Display for ManifoldEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ManifoldEntry::Start => write!(f, "S"),
ManifoldEntry::Empty => write!(f, "."),
ManifoldEntry::Splitter => write!(f, "^"),
}
}
}
type Parsed = Grid<ManifoldEntry>;
#[inline(never)]
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
let line_len = input.find(b"\n").with_context(|| "No newline found")?;
Ok(Grid::new(
input
.iter()
.filter(|&&v| v != b'\n')
.map(|&v| match v {
b'S' => Ok(ManifoldEntry::Start),
b'.' => Ok(ManifoldEntry::Empty),
b'^' => Ok(ManifoldEntry::Splitter),
_ => color_eyre::eyre::bail!("Invalid splitter entry: {}", v as char),
})
.collect::<Result<_, _>>()?,
line_len,
))
}
fn manifold_traversal(manifold: &Grid<ManifoldEntry>) -> (u64, u64) {
let mut lines = manifold.lines();
let start_line = lines.next().unwrap();
let start = start_line
.iter()
.position(|v| *v == ManifoldEntry::Start)
.unwrap();
let mut split_count = 0;
let mut beams = vec![0; start_line.len()];
beams[start] = 1;
loop {
let Some(line) = lines.next() else {
break;
};
assert!(line.iter().all(|v| *v == ManifoldEntry::Empty));
let Some(line) = lines.next() else {
break;
};
let mut new_beams = vec![0; start_line.len()];
for (beam, count) in beams.iter().enumerate().filter(|&(_, &v)| v != 0) {
match &line[beam] {
ManifoldEntry::Start => panic!("Multiple starts"),
ManifoldEntry::Empty => new_beams[beam] += count,
ManifoldEntry::Splitter => {
split_count += 1;
new_beams[beam - 1] += count;
new_beams[beam + 1] += count;
}
}
}
beams = new_beams;
}
(split_count, beams.iter().sum())
}
#[inline(never)]
pub fn part1(input: Parsed) {
let (split_count, _) = manifold_traversal(&input);
print_res!("Split count: {split_count}");
}
#[inline(never)]
pub fn part2(input: Parsed) {
let (_, path_count) = manifold_traversal(&input);
print_res!("Path count: {path_count}");
}
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(())
}

View file

@ -41,6 +41,14 @@ impl<T> Grid<T> {
(0..line_len).flat_map(move |l| (0..col_len).map(move |c| (l, c))) (0..line_len).flat_map(move |l| (0..col_len).map(move |c| (l, c)))
} }
pub fn line(&self, index: usize) -> &[T] {
&self.values[index * self.line_len..(index + 1) * self.line_len]
}
pub fn lines(&self) -> impl Iterator<Item = &[T]> {
(0..self.col_len).map(|i| self.line(i))
}
} }
impl<T: PartialEq + Eq> Grid<T> { impl<T: PartialEq + Eq> Grid<T> {