day01 finished
This commit is contained in:
parent
284f099d3e
commit
68fefd064a
9 changed files with 2487 additions and 164 deletions
|
|
@ -1,4 +1,8 @@
|
|||
use itertools::Itertools;
|
||||
use std::num::ParseIntError;
|
||||
|
||||
use anyhow::Result;
|
||||
use thiserror::Error;
|
||||
|
||||
use super::template::{DayTrait, ResultType};
|
||||
|
||||
|
|
@ -10,11 +14,82 @@ impl DayTrait for Day {
|
|||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, lines: String) -> Result<ResultType> {
|
||||
Ok(ResultType::NoResult)
|
||||
fn part1(&self, lines: &str) -> Result<ResultType> {
|
||||
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> {
|
||||
Ok(ResultType::NoResult)
|
||||
fn part2(&self, lines: &str) -> 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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,50 @@
|
|||
use anyhow::Result;
|
||||
|
||||
use super::template::{Day, ResultType};
|
||||
use super::template::{DayTrait, ResultType};
|
||||
|
||||
pub struct Day;
|
||||
const DAY_NUMBER: usize = 0;
|
||||
|
||||
impl DayTemplate for Day {
|
||||
pub struct Day;
|
||||
|
||||
impl DayTrait for Day {
|
||||
fn get_day_number(&self) -> usize {
|
||||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, lines: String) -> Result<ResultType> {
|
||||
fn part1(&self, _lines: &str) -> Result<ResultType> {
|
||||
Ok(ResultType::NoResult)
|
||||
}
|
||||
|
||||
fn part2(&self, lines: String) -> Result<ResultType> {
|
||||
fn part2(&self, _lines: &str) -> Result<ResultType> {
|
||||
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;
|
||||
pub mod day_provider;
|
||||
mod template;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum TemplateError {
|
||||
#[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
|
||||
}
|
||||
}
|
||||
pub use template::DayTrait;
|
||||
pub use template::ResultType;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
use anyhow::Result;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ResultType {
|
||||
IntResult(i64),
|
||||
StringResult(String),
|
||||
LinesResult(String),
|
||||
LinesResult(Vec<String>),
|
||||
NoResult,
|
||||
}
|
||||
|
||||
pub trait DayTrait {
|
||||
fn get_day_number(&self) -> usize;
|
||||
fn part1(&self, lines: String) -> Result<ResultType>;
|
||||
fn part2(&self, lines: String) -> Result<ResultType>;
|
||||
fn part1(&self, lines: &str) -> Result<ResultType>;
|
||||
fn part2(&self, lines: &str) -> Result<ResultType>;
|
||||
}
|
||||
|
|
|
|||
87
src/main.rs
87
src/main.rs
|
|
@ -1,27 +1,84 @@
|
|||
mod common;
|
||||
mod days;
|
||||
mod macros;
|
||||
use std::error::Error;
|
||||
|
||||
use anyhow::Result;
|
||||
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>> {
|
||||
let day_provider = DayProvider::create();
|
||||
|
||||
//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)? {
|
||||
fn output(day: usize, part: usize, result: ResultType) -> () {
|
||||
match result {
|
||||
ResultType::IntResult(value) => {
|
||||
println!("Day {:02} part {}: {}", day.get_day_number(), 1, value);
|
||||
println!("Day {:02} part {}: {}", day, part, value);
|
||||
}
|
||||
ResultType::StringResult(_) => todo!(),
|
||||
ResultType::LinesResult(_) => todo!(),
|
||||
ResultType::NoResult => todo!(),
|
||||
ResultType::StringResult(value) => {
|
||||
println!("Day {:02} part {}: {}", day, part, value);
|
||||
}
|
||||
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(())
|
||||
}
|
||||
|
||||
#[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