day 12 part 1
This commit is contained in:
parent
2ee9c069d8
commit
0a4ce052ee
2 changed files with 1109 additions and 0 deletions
1000
inputs/day12.txt
Normal file
1000
inputs/day12.txt
Normal file
File diff suppressed because it is too large
Load diff
109
src/bin/day12.rs
Normal file
109
src/bin/day12.rs
Normal 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(())
|
||||||
|
}
|
Loading…
Reference in a new issue