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) = 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::)(s) } fn all_elf_parse(inp: &str) -> IResult<&str, Vec> { separated_list1(count(line_ending, 2), elf_parser)(inp) } pub fn parse(inp: String) -> Vec { 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") ) } }