use nom::{ bytes::complete::tag, character::complete::{self, newline}, combinator::map, multi::separated_list1, sequence::separated_pair, IResult, }; fn parse_input(input: &str) -> IResult<&str, Vec<(u64, u64, u64)>> { let (input, dimensions) = separated_list1( newline, map( separated_pair( complete::u64, tag("x"), separated_pair(complete::u64, tag("x"), complete::u64), ), |(x, (y, z))| (x, y, z), ), )(input)?; Ok((input, dimensions)) } fn solve_first(dimensions: &[(u64, u64, u64)]) -> u64 { dimensions .iter() .map(|&(l, w, h)| { 2 * l * w + 2 * w * h + 2 * l * h + std::cmp::min(l * w, std::cmp::min(w * h, h * l)) }) .sum() } fn solve_second(dimensions: &[(u64, u64, u64)]) -> u64 { dimensions .iter() .map(|&(l, w, h)| smallest_perimeter(l, w, h) + l * w * h) .sum() } fn smallest_perimeter(l: u64, w: u64, h: u64) -> u64 { (l + w + h - std::cmp::max(l, std::cmp::max(w, h))) * 2 } fn main() { println!("Hello, this is Patrick!"); let input_txt = include_str!("../input.txt"); let (_rest, dimensions) = parse_input(input_txt).unwrap_or(("", vec![])); let first_result = solve_first(&dimensions[..]); println!( "The elves will need {} square feet of wrapping paper", first_result ); let second_result = solve_second(&dimensions[..]); println!("The elves will need {} feet of ribbon", second_result); }