From c7afb011663b6cf379bc2528d78fcdf71ae3027e Mon Sep 17 00:00:00 2001 From: Mads Jensen Date: Tue, 16 Jul 2024 16:17:04 +0200 Subject: [PATCH] Initial implementation - failing --- Cargo.lock | 5 ++ bin/Cargo.toml | 3 +- lib/oasis/Cargo.toml | 6 ++ lib/oasis/src/lib.rs | 136 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 lib/oasis/Cargo.toml create mode 100644 lib/oasis/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c244f5c..af7abcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ dependencies = [ "cube_game", "gondola_lift", "network_nodes", + "oasis", "scratchcard", "trebuchet", ] @@ -40,6 +41,10 @@ version = "0.1.0" name = "network_nodes" version = "0.1.0" +[[package]] +name = "oasis" +version = "0.1.0" + [[package]] name = "scratchcard" version = "0.1.0" diff --git a/bin/Cargo.toml b/bin/Cargo.toml index 013e6fa..3152051 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -13,4 +13,5 @@ scratchcard = { path = "../lib/scratchcard" } almanac = { path = "../lib/almanac" } boat_race = { path = "../lib/boat_race" } camel_cards = { path = "../lib/camel_cards" } -network_nodes = { path = "../lib/network_nodes" } \ No newline at end of file +network_nodes = { path = "../lib/network_nodes" } +oasis = { path = "../lib/oasis" } \ No newline at end of file diff --git a/lib/oasis/Cargo.toml b/lib/oasis/Cargo.toml new file mode 100644 index 0000000..f379a68 --- /dev/null +++ b/lib/oasis/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "oasis" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/lib/oasis/src/lib.rs b/lib/oasis/src/lib.rs new file mode 100644 index 0000000..da9796c --- /dev/null +++ b/lib/oasis/src/lib.rs @@ -0,0 +1,136 @@ +use std::{num::ParseIntError, str::FromStr}; + +#[derive(Debug)] +pub enum OasisError { + ParseHistory(ParseIntError), +} + +impl From for OasisError { + fn from(value: ParseIntError) -> Self { + Self::ParseHistory(value) + } +} + +pub type Value = u32; + +#[derive(Debug, Clone)] +pub struct Layer(Vec); + +impl Layer { + #[inline(always)] + fn is_all_zero(&self) -> bool { + println!("Is zero? {self:?}"); + let sum = self.0.iter().sum::(); + println!("Sum: {sum}"); + sum == 0 + } + + #[inline(always)] + pub fn get_next_layer(&self) -> Option { + let next = Self( + self.0 + .windows(2) + .map(|a| { + let (a, b) = (a[0], a[1]); + let diff = a.abs_diff(b); + println!("Diff {a} | {b} = {diff}"); + diff + }) + .collect(), + ); + + if next.is_all_zero() { + return None; + } + + Some(next) + } + + #[inline(always)] + pub fn last_value(&self) -> Option<&Value> { + self.0.last() + } +} + +#[derive(Debug)] +pub struct History(Layer); + +impl FromStr for History { + type Err = OasisError; + + fn from_str(s: &str) -> Result { + Ok(Self(Layer( + s.split(' ').map(|x| x.parse::()).collect::>()?, + ))) + } +} + +impl History { + pub fn calculate_next_value(&self) -> Value { + let mut layers = vec![self.0.clone()]; + println!("Calculating layer: {layers:?}"); + + loop { + let Some(current) = layers.last() else { + unreachable!("Always at least one layer!") + }; + + if let Some(next) = current.get_next_layer() { + println!("Pushing next layer: {next:?}"); + layers.push(next); + } else { + break; + } + } + + let mut current = 0u32; + + (layers.len()..0).for_each(|index| { + let above_value = index.checked_sub(1).map_or_else( + || layers.first().expect("No layers").last_value().unwrap_or(&0), + |under| layers[under].last_value().unwrap_or(&0), + ); + + current = dbg!(current.abs_diff(*above_value)); + + println!("New current: {current}"); + }); + + current + } +} + +#[derive(Debug)] +pub struct Report(Vec); + +impl Report { + pub fn get_next_values_sum(&self) -> Value { + self.0.iter().map(|history| history.calculate_next_value()).sum() + } +} + +impl FromStr for Report { + type Err = OasisError; + + fn from_str(s: &str) -> Result { + Ok(Self(s.lines().map(History::from_str).collect::>()?)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE: &str = "0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45"; + + #[test] + fn solution_1() { + let report = Report::from_str(EXAMPLE).expect("Failed to parse"); + + println!("Parsed! {report:?}"); + + assert_eq!(report.get_next_values_sum(), 114); + } +}