Day 12.....

This commit is contained in:
traxys 2025-12-12 13:56:24 +01:00
parent e0df7d08ef
commit d610e7e757
2 changed files with 164 additions and 0 deletions

160
src/bin/day12.rs Normal file
View file

@ -0,0 +1,160 @@
use std::time::Instant;
use aoc_2025::{Grid, load, print_res};
use bstr::{BString, ByteSlice};
use color_eyre::eyre::Context;
#[derive(PartialEq, Eq)]
enum ShapeSlot {
Full,
Empty,
}
pub struct Shape(Grid<ShapeSlot>);
impl std::fmt::Display for ShapeSlot {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ShapeSlot::Full => write!(f, "#"),
ShapeSlot::Empty => write!(f, "."),
}
}
}
impl std::fmt::Debug for Shape {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug)]
pub struct Region {
lines: usize,
cols: usize,
shapes: Vec<u8>,
}
type Parsed = (Vec<Shape>, Vec<Region>);
#[inline(never)]
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
let mut parts = input.split_str("\n\n").peekable();
let mut shapes = Vec::new();
for i in 0.. {
let Some(&part) = parts.peek() else {
color_eyre::eyre::bail!("Unexpected end of input\n");
};
let expect = format!("{i}:\n");
if !part.starts_with_str(&expect) {
break;
}
let part = parts.next().unwrap();
let line_len = part.lines().nth(1).unwrap().len();
let values = part
.lines()
.skip(1)
.flat_map(|l| {
l.iter().map(|&b| match b {
b'.' => Ok(ShapeSlot::Empty),
b'#' => Ok(ShapeSlot::Full),
_ => Err(color_eyre::eyre::eyre!("Invalid grid point: {}", b as char)),
})
})
.collect::<Result<_, _>>()?;
shapes.push(Shape(Grid::new(values, line_len)));
}
let Some(regions) = parts.next() else {
color_eyre::eyre::bail!("Unexpected end on input\n")
};
color_eyre::eyre::ensure!(parts.count() == 0, "Too many parts of the input");
Ok((
shapes,
str::from_utf8(regions)?
.lines()
.map(|line| {
let Some((size, shapes)) = line.split_once(": ") else {
color_eyre::eyre::bail!("Malformed region: {line}");
};
let Some((lines, cols)) = size.split_once('x') else {
color_eyre::eyre::bail!("Malformed region size: {size}");
};
Ok(Region {
lines: lines
.parse()
.wrap_err_with(|| format!("While parsing lines: {lines}"))?,
cols: cols
.parse()
.wrap_err_with(|| format!("While parsing cols: {cols}"))?,
shapes: shapes
.split_whitespace()
.map(|n| {
n.parse()
.wrap_err_with(|| format!("While parsing shape: {n}"))
})
.collect::<Result<_, _>>()?,
})
})
.collect::<Result<_, _>>()?,
))
}
#[inline(never)]
pub fn part1((shapes, regions): Parsed) {
let shape_areas: Vec<_> = shapes.iter().map(|s| s.0.count(&ShapeSlot::Full)).collect();
let mut remain = 0;
for region in regions {
let area = region.lines * region.cols;
let min_area: usize = region
.shapes
.iter()
.zip(&shape_areas)
.map(|(&n, &a)| n as usize * a)
.sum();
// Not enough area to even attempt
if min_area > area {
continue
}
remain += 1;
}
print_res!("Possible solvable: {remain}");
}
#[inline(never)]
pub fn part2(input: Parsed) {
todo!("todo part2")
}
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

@ -69,6 +69,10 @@ impl<T: PartialEq + Eq> Grid<T> {
} }
sum sum
} }
pub fn count(&self, like: &T) -> usize {
self.values.iter().filter(|&v| v == like).count()
}
} }
impl<T> std::ops::Index<(usize, usize)> for Grid<T> { impl<T> std::ops::Index<(usize, usize)> for Grid<T> {