From 91b264ba693907056ff3dca5fa003010925bfce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Ludwig?= Date: Sun, 13 Aug 2023 15:08:31 +0200 Subject: [PATCH] day25 finished --- data/day25/example01.txt | 13 ++++ data/day25/input.txt | 135 +++++++++++++++++++++++++++++++++++++ src/days/day25/mod.rs | 142 +++++++++++++++++++++++++++++++++++++++ src/days/mod.rs | 4 +- 4 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 data/day25/example01.txt create mode 100644 data/day25/input.txt create mode 100644 src/days/day25/mod.rs diff --git a/data/day25/example01.txt b/data/day25/example01.txt new file mode 100644 index 0000000..237ef0c --- /dev/null +++ b/data/day25/example01.txt @@ -0,0 +1,13 @@ +1=-0-2 +12111 +2=0= +21 +2=01 +111 +20012 +112 +1=-1= +1-12 +12 +1= +122 \ No newline at end of file diff --git a/data/day25/input.txt b/data/day25/input.txt new file mode 100644 index 0000000..b5ab655 --- /dev/null +++ b/data/day25/input.txt @@ -0,0 +1,135 @@ +1-- +1- +1--02 +1122-=2-==0-0=1-2 +2=1-==-1022=10 +1==-02211022=000 +101==210-21=2 +11010==0==221=0=02 +11=1101020=02-11 +1=== +10-2 +10=02=-=02 +1-1--112-202--0 +11-=-0-002=0112-1 +2--0-2=02=-22 +1001-2 +1=101=2=2102-201--1 +1-2==1100-- +2-01=--=1-11 +101-=0010-210== +1=-21-022121110 +1==21 +22==1 +2-0-=2=1 +2--0=10-00--2- +1--1=011-2 +1-100-2 +11-1 +112 +222200110-11110-2= +1==2-210-1122=-2022 +2==1-20-2-=-21 +21=1-=0=-1-=-=-12 +210---=-1===-===00 +1--21=01-022=2- +11-= +21-2 +2-22-0 +1==- +1-----01 +1-0-21- +211212-22-12--=2 +1=220=10=20200-0 +21-=11-==20=1 +102-2==2-==-0 +1=0=01- +22=1--0111 +1-----=1==00===0- +20==-1-121- +1=--2--21-202=21 +1-0122=--= +2==-2--===-=-1=-012 +2220=-00-10- +1==0=---10212-1- +1221=-022120 +100112 +2-=0=220-=01-1=12- +1=00 +2122121=2 +2-== +12-21===10220 +1=0 +22-1=--01-==0 +1-2-2202=1=02 +11-===21- +1-22=0102-=-222-1 +1021=0=21=0=11=2-2 +1===2222=0-0= +20=2-=0= +1=2==02-1-100200 +1=1211211---- +12=1=1---=20 +2--2=2=1100020200 +1=0-002-11-10---- +1=1=-1=-0 +1-21=1=02=21=20 +1-=0-002-0=--=0= +20-===-1= +220021012 +12===1001=--=2=1- +1=-02 +21 +2=200222122 +1-2=110111=012=1- +1=02= +101==1-=1=0001 +1=22--1-021 +120 +201-0211 +1-1012211--2=-1= +12=10202=20 +11-22=2=2=-0==1=00 +11=- +12-1--2222 +22 +1120--0== +10=-0=001- +1=00200200= +1-20 +1-0- +10112-202=-011 +11-2= +1-=10=1-0=-21==11200 +11 +12-0-=01--12 +1-=1121-=0 +120-21=-1=10121= +1102-22 +21= +1==--1==---1-== +12=0--=2210-1== +22210=1-=0 +1102-20-1 +1=1=2102 +11--=2==-0 +2=0=1= +21-0-10= +12-212-2=-==102-- +1==0100210-= +12210-0-1 +1=0-2-0= +10-1=211=1-2= +201-0-- +1--2=00=-1-211 +121=-22100=210-- +122-0-1- +2=211 +2=1-=2-2-0001=-1 +1102--11=0=1=10==2 +1==01121-2--0=12 +2=21-20=-0-0 +2-212=21-02=1-2-02 +2=1-0 +10-0-=20 +2=2=201 \ No newline at end of file diff --git a/src/days/day25/mod.rs b/src/days/day25/mod.rs new file mode 100644 index 0000000..154bcf6 --- /dev/null +++ b/src/days/day25/mod.rs @@ -0,0 +1,142 @@ +use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; +use itertools::{unfold, Itertools}; +use std::iter::Sum; +use std::ops::Add; +use std::str::FromStr; +use thiserror::Error; + +const DAY_NUMBER: usize = 25; + +pub struct Day; + +impl DayTrait for Day { + fn get_day_number(&self) -> usize { + DAY_NUMBER + } + + fn part1(&self, lines: &str) -> anyhow::Result { + let snafu: Snafu = split_lines(lines) + .map(|line| line.parse::()) + .collect::, _>>()? + .into_iter() + .sum(); + Ok(ResultType::String(snafu.as_str())) + } + + fn part2(&self, _lines: &str) -> anyhow::Result { + Ok(ResultType::Nothing) + } +} + +impl Snafu { + pub fn as_str(&self) -> String { + let value = self.0; + if value == 0 { + return String::from("0"); + } + + unfold(value, |value| { + if *value == 0 { + return None; + } + let m = (*value + 2) % 5; + *value = (*value + 2 - m) / 5; + Some(m) + }) + .map(|digit| "=-012".chars().nth(digit).unwrap()) + .collect_vec() + .iter() + .rev() + .join("") + } + + fn new(value: i64) -> Result { + if value >= 0 { + Ok(Snafu(value as usize)) + } else { + Err(SnafuError::OnlyNonNegativeSnafus(value)) + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct Snafu(usize); + +impl Add for Snafu { + type Output = Snafu; + + fn add(self, rhs: Self) -> Self::Output { + Snafu(self.0 + rhs.0) + } +} + +impl Sum for Snafu { + fn sum>(iter: I) -> Self { + iter.fold(Snafu(0), Add::add) + } +} + +impl FromStr for Snafu { + type Err = SnafuError; + + fn from_str(s: &str) -> Result { + Snafu::new( + s.chars() + .map(|c| { + "=-012" + .chars() + .position(|d| d == c) + .ok_or_else(|| SnafuError::IllegalChar(c)) + }) + .fold_ok(0, |acc, next| acc * 5 + (next as i64 - 2))?, + ) + } +} + +#[derive(Debug, Error)] +enum SnafuError { + #[error("Illegal Char: {0}")] + IllegalChar(char), + + #[error("Only non negative Snafus exist. Got: {0}")] + OnlyNonNegativeSnafus(i64), +} + +#[cfg(test)] +mod test { + use super::*; + use crate::common::file::read_string; + use anyhow::Result; + + #[test] + fn test_part1() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let expected = ResultType::String(String::from("2=-1=0")); + let result = day.part1(&lines)?; + assert_eq!(result, expected); + + Ok(()) + } + + #[test] + fn test_part2() -> Result<()> { + let day = Day {}; + let lines = read_string(day.get_day_number(), "example01.txt")?; + let expected = ResultType::Nothing; + let result = day.part2(&lines)?; + assert_eq!(result, expected); + + Ok(()) + } + + #[test] + fn parse() -> Result<()> { + let input = String::from("1=-0-2"); + let snafu: Snafu = input.parse()?; + assert_eq!(snafu, Snafu(1747)); + assert_eq!(snafu.as_str(), input); + Ok(()) + } +} diff --git a/src/days/mod.rs b/src/days/mod.rs index 35bfa86..46f8dfc 100644 --- a/src/days/mod.rs +++ b/src/days/mod.rs @@ -22,6 +22,7 @@ mod day21; mod day22; mod day23; mod day24; +mod day25; mod template; pub use template::DayTrait; @@ -31,7 +32,7 @@ pub mod day_provider { use super::*; use thiserror::Error; - const MAX_DAY: usize = 24; + const MAX_DAY: usize = 25; pub fn get_day(day_num: usize) -> Result, ProviderError> { match day_num { @@ -59,6 +60,7 @@ pub mod day_provider { 22 => Ok(Box::new(day22::Day)), 23 => Ok(Box::new(day23::Day)), 24 => Ok(Box::new(day24::Day)), + 25 => Ok(Box::new(day25::Day)), _ => Err(ProviderError::InvalidNumber(day_num)), } }