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 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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
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;
|
mod day01;
|
||||||
pub mod day_provider;
|
mod day02;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
pub use template::DayTrait;
|
pub use template::DayTrait;
|
||||||
pub use template::ResultType;
|
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<()> {
|
fn run(day: Box<dyn DayTrait>, part1: bool, part2: bool) -> Result<()> {
|
||||||
let lines = read_data(day.get_day_number(), "input.txt")?;
|
let lines = read_data(day.get_day_number(), "input.txt")?;
|
||||||
if part1 {
|
if part1 {
|
||||||
output(1, 1, day.part1(&lines)?);
|
output(day.get_day_number(), 1, day.part1(&lines)?);
|
||||||
}
|
}
|
||||||
if part2 {
|
if part2 {
|
||||||
output(1, 2, day.part2(&lines)?);
|
output(day.get_day_number(), 2, day.part2(&lines)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue