advent-2022-rust/src/days/day01/mod.rs
2023-01-28 06:00:12 +01:00

94 lines
2.4 KiB
Rust

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<ResultType> {
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<ResultType> {
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<Vec<i64>, CalorieError> {
Ok(lines
.split("\n")
.batching(|it| {
let result = it
.take_while(|line| line.len() != 0)
.map(|line| line.parse::<i64>())
.collect::<Result<Vec<_>, _>>()
.map(|lst: _| lst.iter().sum::<i64>());
result
.map(|value| if value == 0 { None } else { Some(value) })
.transpose()
})
.collect::<Result<_, _>>()?)
}
}
#[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(())
}
}