86 lines
1.7 KiB
Rust
86 lines
1.7 KiB
Rust
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
|
|
|
use aoc23::read;
|
|
use chumsky::{prelude::*, text::int};
|
|
use std::collections::HashMap;
|
|
|
|
enum Entity {
|
|
Void,
|
|
Symbol(char),
|
|
Number { num: usize, len: usize }
|
|
}
|
|
|
|
impl Entity {
|
|
fn len(&self) -> usize {
|
|
match self {
|
|
Self::Void | Self::Symbol(_) => 1,
|
|
Self::Number { len, .. } => *len
|
|
}
|
|
}
|
|
|
|
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
|
|
choice((
|
|
just('.').map(|_| Self::Void),
|
|
int(10).map(|num: String| Self::Number {
|
|
num: num.parse().unwrap(),
|
|
len: num.len()
|
|
}),
|
|
none_of(['\n']).map(Self::Symbol)
|
|
))
|
|
}
|
|
}
|
|
|
|
struct Line {
|
|
entities: HashMap<usize, Entity>
|
|
}
|
|
|
|
impl Line {
|
|
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
|
|
Entity::parser().repeated().map(|line| {
|
|
let mut col = 0;
|
|
let mut entities = HashMap::new();
|
|
for ent in line {
|
|
let len = ent.len();
|
|
entities.insert(col, ent);
|
|
col += len;
|
|
}
|
|
Line { entities }
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parser() -> impl Parser<char, Vec<Line>, Error = Simple<char>> {
|
|
Line::parser()
|
|
.then_ignore(just("\n"))
|
|
.repeated()
|
|
.then_ignore(end())
|
|
}
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
let grid = read("inputs/day3.txt", parser())?;
|
|
|
|
let mut sum = 0;
|
|
for (i, line) in grid.iter().enumerate() {
|
|
'entities: for (col, ent) in &line.entities {
|
|
let Entity::Number { num, len } = ent else {
|
|
continue;
|
|
};
|
|
|
|
// see if adjacent
|
|
for search_row in i.saturating_sub(1) ..= i + 1 {
|
|
let Some(row) = grid.get(search_row) else {
|
|
continue;
|
|
};
|
|
for search_col in col.saturating_sub(1) ..= col + len {
|
|
if let Some(Entity::Symbol(_)) = row.entities.get(&search_col) {
|
|
sum += num;
|
|
continue 'entities;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("{sum}");
|
|
|
|
Ok(())
|
|
}
|