diff options
Diffstat (limited to '2023/src/bin/day_1.rs')
-rw-r--r-- | 2023/src/bin/day_1.rs | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/2023/src/bin/day_1.rs b/2023/src/bin/day_1.rs index 227aada..fe3ef1e 100644 --- a/2023/src/bin/day_1.rs +++ b/2023/src/bin/day_1.rs @@ -1,8 +1,81 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{alpha1, anychar, line_ending, none_of, one_of}, + combinator::{map, map_opt, map_res, opt, peek, value}, + multi::{many1, separated_list1}, + sequence::pair, + IResult, +}; use std::fs; fn main() -> Result<(), Box<dyn std::error::Error>> { let input = fs::read_to_string("inputs/day_1.txt")?; - dbg!(input); + let parsed = CalibrationInput::parser(&input).unwrap().1; + dbg!(parsed.calibration_sum()); Ok(()) } + +#[derive(Debug)] +struct CalibrationInput(Vec<CalibrationValue>); + +#[derive(Debug)] +struct CalibrationValue(u32); + +#[derive(Debug)] +struct CalibrationDigit(u8); + +impl CalibrationInput { + fn calibration_sum(&self) -> u32 { + self.0.iter().map(|d| d.0).sum() + } + + fn parser(input: &str) -> IResult<&str, Self> { + map( + separated_list1(line_ending, CalibrationValue::parser), + CalibrationInput, + )(input) + } +} + +impl CalibrationValue { + fn parser(input: &str) -> IResult<&str, Self> { + map( + many1(pair( + opt(peek(CalibrationDigit::parser)), // peek is to not consume the 'one' in 'twone' + none_of("\n"), // this is just to advance the input + )), + |digits| { + let digits: Vec<u32> = digits + .into_iter() + .filter_map(|(d, _)| d.map(|d| d.0 as u32)) + .collect(); + CalibrationValue(digits[0] * 10 + digits[digits.len() - 1]) + }, + )(input) + } +} + +impl CalibrationDigit { + fn parser(input: &str) -> IResult<&str, Self> { + map( + alt(( + map(one_of("0123456789"), |c| { + c.to_string().parse::<u8>().unwrap() + }), + value(0, tag("zero")), + value(1, tag("one")), + value(2, tag("two")), + value(3, tag("three")), + value(4, tag("four")), + value(5, tag("five")), + value(6, tag("six")), + value(7, tag("seven")), + value(8, tag("eight")), + value(9, tag("nine")), + )), + CalibrationDigit, + )(input) + } +} |