day01 finished
This commit is contained in:
parent
284f099d3e
commit
68fefd064a
9 changed files with 2487 additions and 164 deletions
|
|
@ -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
14
data/day01/example01.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
1000
|
||||||
|
2000
|
||||||
|
3000
|
||||||
|
|
||||||
|
4000
|
||||||
|
|
||||||
|
5000
|
||||||
|
6000
|
||||||
|
|
||||||
|
7000
|
||||||
|
8000
|
||||||
|
9000
|
||||||
|
|
||||||
|
10000
|
||||||
2355
data/day01/input.txt
2355
data/day01/input.txt
File diff suppressed because it is too large
Load diff
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
21
src/days/day_provider.rs
Normal 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),
|
||||||
|
}
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
87
src/main.rs
87
src/main.rs
|
|
@ -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(¶ms)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue