81 lines
2.1 KiB
Rust
81 lines
2.1 KiB
Rust
use nom::{
|
|
branch::alt,
|
|
bytes::complete::tag,
|
|
character::{
|
|
complete::{anychar, line_ending, satisfy},
|
|
is_alphabetic,
|
|
},
|
|
combinator::{map, map_opt},
|
|
multi::{many1, separated_list1},
|
|
IResult,
|
|
};
|
|
|
|
pub mod inputs;
|
|
mod test;
|
|
|
|
type Int = u32;
|
|
type Line = (Vec<Int>, Vec<Int>);
|
|
|
|
fn parse_single_digit(input: &str) -> IResult<&str, Int> {
|
|
map_opt(anychar, |i: char| i.to_digit(10))(input)
|
|
}
|
|
|
|
fn parse_single_digit_or_word(input: &str) -> IResult<&str, Int> {
|
|
let (_, x) = alt((
|
|
map(tag("one"), |_| 1),
|
|
map(tag("two"), |_| 2),
|
|
map(tag("three"), |_| 3),
|
|
map(tag("four"), |_| 4),
|
|
map(tag("five"), |_| 5),
|
|
map(tag("six"), |_| 6),
|
|
map(tag("seven"), |_| 7),
|
|
map(tag("eight"), |_| 8),
|
|
map(tag("nine"), |_| 9),
|
|
parse_single_digit,
|
|
))(input)?;
|
|
let n = input.get(1..).unwrap_or("");
|
|
Ok((n, x))
|
|
}
|
|
|
|
fn parse_line_sub(
|
|
f: impl FnMut(&str) -> IResult<&str, Int>,
|
|
input: &str,
|
|
) -> IResult<&str, Vec<Option<Int>>> {
|
|
many1(alt((
|
|
map(f, Some),
|
|
map(satisfy(|c| is_alphabetic(c as u8)), |_| None),
|
|
)))(input)
|
|
}
|
|
|
|
fn parse_line(input: &str) -> IResult<&str, Line> {
|
|
let (_, i) = parse_line_sub(parse_single_digit, input)?;
|
|
let i: Vec<Int> = i.into_iter().flatten().collect();
|
|
let (out, j) = parse_line_sub(parse_single_digit_or_word, input)?;
|
|
let j: Vec<Int> = j.into_iter().flatten().collect();
|
|
Ok((out, (i, j)))
|
|
}
|
|
|
|
fn parse_input(input: &str) -> IResult<&str, Vec<Line>> {
|
|
let (res, out) = separated_list1(line_ending, parse_line)(input)?;
|
|
Ok((res, out))
|
|
}
|
|
|
|
pub fn solution(input: &str) -> Result<(Int, Int), String> {
|
|
let (_, input) = parse_input(input).map_err(|e| e.to_string())?;
|
|
let (a, b): (Int, Int) = input
|
|
.into_iter()
|
|
.map(|(ads, bds)| {
|
|
let f = |ds: Vec<Int>| {
|
|
if ds.is_empty() {
|
|
0
|
|
} else {
|
|
let n = ds.len() - 1;
|
|
(ds[0] * 10) + ds[n]
|
|
}
|
|
};
|
|
(f(ads), f(bds))
|
|
})
|
|
.fold((0, 0), |(a, b), (c, d)| (a + c, b + d));
|
|
Ok((a, b))
|
|
}
|