use itertools::Itertools; use std::num::ParseIntError; use thiserror::Error; use super::template::{DayTrait, ResultType}; pub struct Day; const DAY_NUMBER: usize = 1; impl DayTrait for Day { fn get_day_number(&self) -> usize { DAY_NUMBER } fn part1(&self, lines: &str) -> anyhow::Result { let vector = Day::parse(lines)?; let max = vector.iter().max().ok_or(CalorieError::Empty)?; Ok(ResultType::IntResult(*max)) } fn part2(&self, lines: &str) -> anyhow::Result { let vector = Day::parse(lines)?; let sum = vector.iter().sorted_by(|a, b| Ord::cmp(b, a)).take(3).sum(); Ok(ResultType::IntResult(sum)) } } impl Day { fn parse(lines: &str) -> Result, CalorieError> { Ok(lines .split("\n") .batching(|it| { let result = it .take_while(|line| line.len() != 0) .map(|line| line.parse::()) .collect::, _>>() .map(|lst: _| lst.iter().sum::()); result .map(|value| if value == 0 { None } else { Some(value) }) .transpose() }) .collect::>()?) } } #[derive(Debug, Error)] pub enum CalorieError { #[error("Could not parse")] ParseError(#[from] ParseIntError), #[error("Did not get any values.")] Empty, } #[cfg(test)] mod test { use super::*; use crate::common::file::read_data; use anyhow::Result; #[test] fn test_part1() -> Result<()> { let day = Day {}; let lines = read_data(day.get_day_number(), "example01.txt")?; let expected = ResultType::IntResult(24_000); let result = day.part1(&lines)?; assert_eq!(result, expected); Ok(()) } #[test] fn test_part2() -> Result<()> { let day = Day {}; let lines = read_data(day.get_day_number(), "example01.txt")?; let expected = ResultType::IntResult(45_000); let result = day.part2(&lines)?; assert_eq!(result, expected); Ok(()) } #[test] fn test_parse() -> Result<()> { let lines = read_data(DAY_NUMBER, "example01.txt")?; let expected = vec![6000, 4000, 11000, 24000, 10000]; let result = Day::parse(&lines)?; assert_eq!(result, expected); Ok(()) } }