day 12 part 1

This commit is contained in:
Dominic 2023-12-12 18:02:07 +01:00
parent 2ee9c069d8
commit 0a4ce052ee
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
2 changed files with 1109 additions and 0 deletions

1000
inputs/day12.txt Normal file

File diff suppressed because it is too large Load diff

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

@ -0,0 +1,109 @@
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
use aoc23::read;
use chumsky::{prelude::*, text::int};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Cell {
Working,
Broken,
Unknown
}
impl Cell {
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
choice((
just('.').map(|_| Self::Working),
just('#').map(|_| Self::Broken),
just('?').map(|_| Self::Unknown)
))
}
}
struct Row {
cells: Vec<Cell>,
expected: Vec<u32>
}
impl Row {
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
Cell::parser()
.repeated()
.then_ignore(just(" "))
.then(int(10).separated_by(just(",")))
.map(|(cells, expected)| Self {
cells,
expected: expected
.into_iter()
.map(|num: String| num.parse().unwrap())
.collect()
})
}
}
fn parser() -> impl Parser<char, Vec<Row>, Error = Simple<char>> {
Row::parser()
.then_ignore(just("\n"))
.repeated()
.then_ignore(end())
}
fn combinations(
peeked_cell: Option<Cell>,
cells: &[Cell],
current: u32,
expected: &[u32]
) -> u64 {
let res = match (
peeked_cell.or_else(|| cells.first().copied()),
expected.first().copied()
) {
// streak but no more expectations
(_, None) if current != 0 => 0,
// everything empty, everything fine
(None, None) => 1,
// no more cells with expected containing just the current streak
(None, Some(expectation)) if expectation == current && expected.len() == 1 => 1,
// no more cells but expected doesn't match
(None, Some(_)) => 0,
// working cell with no current streak
(Some(Cell::Working), _) if current == 0 => {
combinations(None, &cells[1 ..], 0, expected)
},
// working cell with current streak that is expected
(Some(Cell::Working), Some(expectation)) if expectation == current => {
combinations(None, &cells[1 ..], 0, &expected[1 ..])
},
// working cell with current streak that doesn't match
(Some(Cell::Working), _) => 0,
// broken cell
(Some(Cell::Broken), _) => {
combinations(None, &cells[1 ..], current + 1, expected)
},
// unknown cell
(Some(Cell::Unknown), _) => {
combinations(Some(Cell::Working), cells, current, expected)
+ combinations(Some(Cell::Broken), cells, current, expected)
},
};
// eprintln!(
// "combinations({peeked_cell:?}, {cells:?}, {current}, {expected:?}) = {res}"
// );
res
}
fn main() -> anyhow::Result<()> {
let grid = read("inputs/day12.txt", parser())?;
println!(
"{}",
grid.iter()
.map(|row| combinations(None, &row.cells, 0, &row.expected))
.sum::<u64>()
);
Ok(())
}