1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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")?;
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)
}
}
|