day02 finished
This commit is contained in:
parent
68fefd064a
commit
eb1ce68486
9 changed files with 2758 additions and 30 deletions
|
|
@ -1,10 +1,6 @@
|
|||
# Advent of Code 2019
|
||||
# Advent of Code 2022
|
||||
|
||||
These are my solutions for [Advent of Code 2019](https://adventofcode.com/). Thanks to [Eric Wastl](http://was.tl) for the great puzzles and a great time I had solving them.
|
||||
|
||||
These are my attempts for the year 2019. I wanted to learn Rust (started at version 1.48 finished at 1.49) and I would say I succeeded to get the hange of this strange language for just a bit.
|
||||
|
||||
My goal was to finish at least one puzzle on a given day. And to try to use a few additional crates as possible. I did not quite succeed in the former, but at least I solved every single puzzle alone. I am quite pround of a few of them. I learned a lot. Not only about rust, but also on how to approach certain riddles.
|
||||
These are my solutions for [Advent of Code 2022](https://adventofcode.com/). Thanks to [Eric Wastl](http://was.tl) for the great puzzles and a great time I had solving them.
|
||||
|
||||
If you look at the code and see ways I could improve it, please do not hesitate to contact me. I am always grateful for everything that makes me a better programmer.
|
||||
|
||||
|
|
|
|||
3
data/day02/example01.txt
Normal file
3
data/day02/example01.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
A Y
|
||||
B X
|
||||
C Z
|
||||
2500
data/day02/input.txt
Normal file
2500
data/day02/input.txt
Normal file
File diff suppressed because it is too large
Load diff
0
data/day__/example01.txt
Normal file
0
data/day__/example01.txt
Normal file
0
data/day__/input.txt
Normal file
0
data/day__/input.txt
Normal file
225
src/days/day02/mod.rs
Normal file
225
src/days/day02/mod.rs
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use super::template::{DayTrait, ResultType};
|
||||
use anyhow::Result;
|
||||
use thiserror::Error;
|
||||
|
||||
const DAY_NUMBER: usize = 2;
|
||||
|
||||
pub struct Day;
|
||||
|
||||
impl DayTrait for Day {
|
||||
fn get_day_number(&self) -> usize {
|
||||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, lines: &str) -> Result<ResultType> {
|
||||
let sum = lines
|
||||
.split("\n")
|
||||
.map(RPS::parse_line)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
.into_iter()
|
||||
.map(|(first, second)| second.asses_pair(&first))
|
||||
.sum();
|
||||
|
||||
Ok(ResultType::IntResult(sum))
|
||||
}
|
||||
|
||||
fn part2(&self, lines: &str) -> Result<ResultType> {
|
||||
let sum = lines
|
||||
.split("\n")
|
||||
.map(Strategy::parse_line)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
.into_iter()
|
||||
.map(|(first, second)| second.fullfill(&first).asses_pair(&first))
|
||||
.sum();
|
||||
|
||||
Ok(ResultType::IntResult(sum))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum RPSError {
|
||||
#[error("No a valid RPS: {0}")]
|
||||
ParseError(String),
|
||||
|
||||
#[error("Not a logal RPS line: {0}")]
|
||||
IllegalLine(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
enum RPS {
|
||||
Rock,
|
||||
Paper,
|
||||
Scissors,
|
||||
}
|
||||
|
||||
impl RPS {
|
||||
pub fn parse_line(line: &str) -> Result<(Self, Self)> {
|
||||
let mut parts = line.split(" ");
|
||||
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
||||
Err(RPSError::IllegalLine(line.to_owned()))?
|
||||
};
|
||||
|
||||
let first = RPS::try_from(first)?;
|
||||
let second = RPS::try_from(second)?;
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
pub fn value(&self) -> i64 {
|
||||
match self {
|
||||
RPS::Rock => 1,
|
||||
RPS::Paper => 2,
|
||||
RPS::Scissors => 3,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn asses_pair(&self, other: &Self) -> i64 {
|
||||
let outcome = match self.partial_cmp(other) {
|
||||
Some(Ordering::Less) => 0,
|
||||
Some(Ordering::Equal) => 3,
|
||||
Some(Ordering::Greater) => 6,
|
||||
None => unreachable!(),
|
||||
};
|
||||
outcome + self.value()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for RPS {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(RPS::Rock, RPS::Paper) | (RPS::Paper, RPS::Scissors) | (RPS::Scissors, RPS::Rock) => {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
(RPS::Rock, RPS::Scissors) | (RPS::Paper, RPS::Rock) | (RPS::Scissors, RPS::Paper) => {
|
||||
Some(Ordering::Greater)
|
||||
}
|
||||
_ => Some(Ordering::Equal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for RPS {
|
||||
type Error = RPSError;
|
||||
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
"A" | "X" => Ok(RPS::Rock),
|
||||
"B" | "Y" => Ok(RPS::Paper),
|
||||
"C" | "Z" => Ok(RPS::Scissors),
|
||||
_ => Err(RPSError::ParseError(value.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
enum Strategy {
|
||||
Loose,
|
||||
Draw,
|
||||
Win,
|
||||
}
|
||||
|
||||
impl Strategy {
|
||||
pub fn parse_line(line: &str) -> Result<(RPS, Self)> {
|
||||
let mut parts = line.split(" ");
|
||||
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
||||
Err(RPSError::IllegalLine(line.to_owned()))?
|
||||
};
|
||||
|
||||
let first = RPS::try_from(first)?;
|
||||
let second = Strategy::try_from(second)?;
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
pub fn fullfill(&self, other: &RPS) -> RPS {
|
||||
match (other, self) {
|
||||
(_, Strategy::Draw) => *other,
|
||||
(RPS::Rock, Strategy::Win) | (RPS::Scissors, Strategy::Loose) => RPS::Paper,
|
||||
(RPS::Paper, Strategy::Win) | (RPS::Rock, Strategy::Loose) => RPS::Scissors,
|
||||
(RPS::Scissors, Strategy::Win) | (RPS::Paper, Strategy::Loose) => RPS::Rock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Strategy {
|
||||
type Error = RPSError;
|
||||
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
"X" => Ok(Strategy::Loose),
|
||||
"Y" => Ok(Strategy::Draw),
|
||||
"Z" => Ok(Strategy::Win),
|
||||
_ => Err(RPSError::ParseError(value.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::common::file::read_data;
|
||||
use anyhow::Result;
|
||||
|
||||
#[test]
|
||||
fn test_parse() -> Result<()> {
|
||||
let input = "A Y";
|
||||
let expected = (RPS::Rock, RPS::Paper);
|
||||
let result = RPS::parse_line(input)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assess() -> Result<()> {
|
||||
let first = RPS::Scissors;
|
||||
let second = RPS::Paper;
|
||||
let expected = 9;
|
||||
let result = first.asses_pair(&second);
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1() -> Result<()> {
|
||||
let day = Day {};
|
||||
let lines = read_data(day.get_day_number(), "example01.txt")?;
|
||||
let expected = ResultType::IntResult(15);
|
||||
let result = day.part1(&lines)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_strategy() -> Result<()> {
|
||||
let input = "A Y";
|
||||
let expected = (RPS::Rock, Strategy::Draw);
|
||||
let result = Strategy::parse_line(input)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assess_stragety() -> Result<()> {
|
||||
let first = RPS::Scissors;
|
||||
let second = Strategy::Win;
|
||||
let expected = RPS::Rock;
|
||||
let result = second.fullfill(&first);
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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,6 +1,31 @@
|
|||
mod day01;
|
||||
pub mod day_provider;
|
||||
mod day02;
|
||||
mod template;
|
||||
|
||||
pub use template::DayTrait;
|
||||
pub use template::ResultType;
|
||||
|
||||
pub mod day_provider {
|
||||
use super::*;
|
||||
use thiserror::Error;
|
||||
|
||||
const MAX_DAY: usize = 2;
|
||||
|
||||
pub fn get_day(day_num: usize) -> Result<Box<dyn DayTrait>, ProviderError> {
|
||||
match day_num {
|
||||
1 => Ok(Box::new(day01::Day)),
|
||||
2 => Ok(Box::new(day02::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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ fn output(day: usize, part: usize, result: ResultType) -> () {
|
|||
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)?);
|
||||
output(day.get_day_number(), 1, day.part1(&lines)?);
|
||||
}
|
||||
if part2 {
|
||||
output(1, 2, day.part2(&lines)?);
|
||||
output(day.get_day_number(), 2, day.part2(&lines)?);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue