day01 finished

This commit is contained in:
Ruediger Ludwig 2023-01-26 21:52:09 +01:00
parent 284f099d3e
commit 68fefd064a
9 changed files with 2487 additions and 164 deletions

View file

@ -5,5 +5,6 @@ authors = ["Ruediger Ludwig <github@savinien.de>"]
edition = "2021" edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.68" anyhow = "1.0"
thiserror = "1.0.38" itertools = "0.10"
thiserror = "1.0"

14
data/day01/example01.txt Normal file
View file

@ -0,0 +1,14 @@
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,8 @@
use itertools::Itertools;
use std::num::ParseIntError;
use anyhow::Result; use anyhow::Result;
use thiserror::Error;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
@ -10,11 +14,82 @@ impl DayTrait for Day {
DAY_NUMBER DAY_NUMBER
} }
fn part1(&self, lines: String) -> Result<ResultType> { fn part1(&self, lines: &str) -> Result<ResultType> {
Ok(ResultType::NoResult) let vector = Day::parse(lines)?;
let max = vector.iter().max().ok_or(CalorieError::Empty)?;
Ok(ResultType::IntResult(*max))
} }
fn part2(&self, lines: String) -> Result<ResultType> { fn part2(&self, lines: &str) -> Result<ResultType> {
Ok(ResultType::NoResult) 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(())
} }
} }

View file

@ -1,20 +1,50 @@
use anyhow::Result; use anyhow::Result;
use super::template::{Day, ResultType}; use super::template::{DayTrait, ResultType};
pub struct Day;
const DAY_NUMBER: usize = 0; const DAY_NUMBER: usize = 0;
impl DayTemplate for Day { pub struct Day;
impl DayTrait for Day {
fn get_day_number(&self) -> usize { fn get_day_number(&self) -> usize {
DAY_NUMBER DAY_NUMBER
} }
fn part1(&self, lines: String) -> Result<ResultType> { fn part1(&self, _lines: &str) -> Result<ResultType> {
Ok(ResultType::NoResult) Ok(ResultType::NoResult)
} }
fn part2(&self, lines: String) -> Result<ResultType> { fn part2(&self, _lines: &str) -> Result<ResultType> {
Ok(ResultType::NoResult) Ok(ResultType::NoResult)
} }
} }
#[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::NoResult;
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::NoResult;
let result = day.part2(&lines)?;
assert_eq!(result, expected);
Ok(())
}
}

21
src/days/day_provider.rs Normal file
View file

@ -0,0 +1,21 @@
use super::{day01, DayTrait};
use thiserror::Error;
const MAX_DAY: usize = 1;
pub fn get_day(day_num: usize) -> Result<Box<dyn DayTrait>, ProviderError> {
match day_num {
1 => Ok(Box::new(day01::Day)),
_ => Err(ProviderError::InvalidNumber(day_num)),
}
}
pub fn get_all_days() -> impl Iterator<Item = Box<dyn DayTrait>> {
(1..=MAX_DAY).map(|day_num| get_day(day_num).expect("Must never happen"))
}
#[derive(Debug, Error)]
pub enum ProviderError {
#[error("Not a valid day number: {0}")]
InvalidNumber(usize),
}

View file

@ -1,38 +1,6 @@
use anyhow::Result;
use self::{day01::Day, template::DayTrait};
use thiserror::Error;
pub use template::ResultType;
mod day01; mod day01;
pub mod day_provider;
mod template; mod template;
#[derive(Debug, Error)] pub use template::DayTrait;
pub enum TemplateError { pub use template::ResultType;
#[error("Not a valid day number: {0}")]
InvalidNumber(usize),
}
pub struct DayProvider {
days: Vec<Box<dyn DayTrait>>,
}
impl DayProvider {
pub fn create() -> DayProvider {
DayProvider {
days: vec![Box::new(Day)],
}
}
pub fn get_day(&self, day_num: usize) -> Result<&Box<dyn DayTrait>> {
Ok(self
.days
.get(day_num - 1)
.ok_or(TemplateError::InvalidNumber(day_num))?)
}
pub fn get_all_days(&self) -> &[Box<dyn DayTrait>] {
&self.days
}
}

View file

@ -1,14 +1,16 @@
use anyhow::Result; use anyhow::Result;
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq)]
pub enum ResultType { pub enum ResultType {
IntResult(i64), IntResult(i64),
StringResult(String), StringResult(String),
LinesResult(String), LinesResult(Vec<String>),
NoResult, NoResult,
} }
pub trait DayTrait { pub trait DayTrait {
fn get_day_number(&self) -> usize; fn get_day_number(&self) -> usize;
fn part1(&self, lines: String) -> Result<ResultType>; fn part1(&self, lines: &str) -> Result<ResultType>;
fn part2(&self, lines: String) -> Result<ResultType>; fn part2(&self, lines: &str) -> Result<ResultType>;
} }

View file

@ -1,27 +1,84 @@
mod common; mod common;
mod days; mod days;
mod macros; mod macros;
use std::error::Error;
use anyhow::Result;
use common::file::read_data; use common::file::read_data;
use days::{DayProvider, ResultType}; use days::{day_provider, DayTrait, ResultType};
use std::env;
use thiserror::Error;
fn main() -> Result<(), Box<dyn Error>> { fn output(day: usize, part: usize, result: ResultType) -> () {
let day_provider = DayProvider::create(); match result {
//let params = env::args().skip(1).collect::<Vec<_>>();
let day = day_provider.get_day(1)?;
let lines = read_data(day.get_day_number(), "input.txt")?;
match day.part1(lines)? {
ResultType::IntResult(value) => { ResultType::IntResult(value) => {
println!("Day {:02} part {}: {}", day.get_day_number(), 1, value); println!("Day {:02} part {}: {}", day, part, value);
} }
ResultType::StringResult(_) => todo!(), ResultType::StringResult(value) => {
ResultType::LinesResult(_) => todo!(), println!("Day {:02} part {}: {}", day, part, value);
ResultType::NoResult => todo!(), }
ResultType::LinesResult(value) => {
println!("Day {:02} part {}: {}", day, part, value[0]);
for line in &value[1..] {
println!(" part : {}", line);
}
}
ResultType::NoResult => {
println!("Day {:02} part {}: (None)", day, part);
}
}
}
fn run(day: Box<dyn DayTrait>, part1: bool, part2: bool) -> Result<()> {
let lines = read_data(day.get_day_number(), "input.txt")?;
if part1 {
output(1, 1, day.part1(&lines)?);
}
if part2 {
output(1, 2, day.part2(&lines)?);
} }
Ok(()) Ok(())
} }
#[derive(Debug, Error)]
enum ParamError {
#[error("Too many Parameters: {0}")]
TooManyParameters(usize),
#[error("Unknown Part: {0}")]
UnknownPart(usize),
}
fn run_on_parameters(params: &[String]) -> Result<()> {
match params.len() {
0 => {
for day in day_provider::get_all_days() {
run(day, true, true)?;
}
}
1 => {
let mut parts = params[0].split("/");
if let Some(day_str) = parts.next() {
let day_number = day_str.parse::<usize>()?;
let day = day_provider::get_day(day_number)?;
if let Some(part_str) = parts.next() {
match part_str.parse::<usize>()? {
1 => run(day, true, false)?,
2 => run(day, false, true)?,
p => Err(ParamError::UnknownPart(p))?,
}
} else {
run(day, true, true)?;
}
}
}
n => Err(ParamError::TooManyParameters(n))?,
}
Ok(())
}
fn main() -> Result<()> {
let params = env::args().skip(1).collect::<Vec<_>>();
run_on_parameters(&params)
}