61 lines
1.4 KiB
Rust
61 lines
1.4 KiB
Rust
use nom::character::complete::{digit1, line_ending};
|
|
use nom::combinator::map_res;
|
|
use nom::multi::{count, separated_list0, separated_list1};
|
|
use nom::IResult;
|
|
|
|
fn elf_parser(s: &str) -> IResult<&str, usize> {
|
|
let (rest, matched): (&str, Vec<usize>) = separated_list0(line_ending, get_digits)(s)?;
|
|
Ok((rest, matched.iter().sum()))
|
|
}
|
|
|
|
fn get_digits(s: &str) -> IResult<&str, usize> {
|
|
map_res(digit1, str::parse::<usize>)(s)
|
|
}
|
|
|
|
fn all_elf_parse(inp: &str) -> IResult<&str, Vec<usize>> {
|
|
separated_list1(count(line_ending, 2), elf_parser)(inp)
|
|
}
|
|
|
|
pub fn parse(inp: String) -> Vec<usize> {
|
|
if let Ok((_, elves)) = all_elf_parse(&inp) {
|
|
elves.clone()
|
|
} else {
|
|
panic!()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_get_digits() {
|
|
assert_eq!(Ok(("", 123)), get_digits("123"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_one_line_make_elf() {
|
|
assert_eq!(Ok(("", 123)), elf_parser("123"))
|
|
}
|
|
|
|
#[test]
|
|
fn test_multiline_make_elf() {
|
|
assert_eq!(Ok(("", 1368)), elf_parser("123\n456\n789"))
|
|
}
|
|
|
|
#[test]
|
|
fn test_multiple_elf() {
|
|
assert_eq!(
|
|
Ok(("\n\n123\n123", 1368)),
|
|
elf_parser("123\n456\n789\n\n123\n123")
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn test_multiple_elf_parsed() {
|
|
assert_eq!(
|
|
Ok(("", vec![1368, 246])),
|
|
all_elf_parse("123\n456\n789\n\n123\n123")
|
|
)
|
|
}
|
|
}
|