Skip to content

Commit

Permalink
day9 done
Browse files Browse the repository at this point in the history
  • Loading branch information
madser123 committed Jul 17, 2024
1 parent 97fd698 commit 1ae3445
Showing 1 changed file with 48 additions and 20 deletions.
68 changes: 48 additions & 20 deletions lib/oasis/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use std::{num::ParseIntError, str::FromStr};

/// Errors than can occur during an Oasis report
#[derive(Debug)]
pub enum OasisError {
/// Failed to parse History
ParseHistory(ParseIntError),

/// No histories found when parsing
NoHistories,
}

impl From<ParseIntError> for OasisError {
Expand All @@ -11,58 +16,58 @@ impl From<ParseIntError> for OasisError {
}
}

/// A value from an Oasis report
pub type Value = i64;

/// A Layer in a History
#[derive(Debug, Clone)]
pub struct Layer(Vec<Value>);

impl Layer {
#[inline(always)]
/// Checks if all values in the layer is `0`
fn is_all_zero(&self) -> bool {
self.0.iter().all(|n| *n == 0)
}

#[inline(always)]
/// Calculates the differences between values in the layer, to create the layer below it.
pub fn get_next_layer(&self) -> Option<Self> {
if self.is_all_zero() {
return None;
}

// Get differences
let next = self.0.windows(2).map(|a| a[1] - a[0]).collect();

Some(Self(next))
}

#[inline(always)]
/// Returns the last value of the layer, if any
pub fn last_value(&self) -> Option<&Value> {
self.0.last()
}

#[inline(always)]
/// Returns the first value of the layer, if any
pub fn first_value(&self) -> Option<&Value> {
self.0.first()
}
}

/// A History
#[derive(Debug)]
pub struct History(Layer);
pub struct History(Vec<Layer>);

impl FromStr for History {
type Err = OasisError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(Layer(
// Create a vector, containing the first layer
let mut layers = vec![Layer(
s.split_whitespace()
.map(|x| x.parse::<Value>())
.collect::<Result<_, _>>()?,
)))
}
}

impl History {
fn get_layers(&self) -> Vec<Layer> {
let mut layers = vec![self.0.clone()];
)];

// Calculate the rest of the layers
loop {
let Some(current) = layers.last() else {
unreachable!("Always at least one layer!")
Expand All @@ -75,42 +80,59 @@ impl History {
}
}

layers
Ok(Self(layers))
}
}

impl History {
/// Calculates the next value in the history
pub fn calculate_next_value(&self) -> Value {
self.get_layers()
self.0
.iter()
.rev()
.fold(0, |acc, layer| layer.last_value().map_or(acc, |value| acc + value))
}

/// Calculates the previous value in the history
pub fn calculate_prev_value(&self) -> Value {
self.get_layers()
.iter()
.rev()
.fold(0, |acc, layer| layer.first_value().map_or(acc, |value| acc + value))
self.0.iter().rev().fold(0, |below, layer| {
layer.first_value().map_or(below, |value| value - below)
})
}
}

/// An Oasis-Report
#[derive(Debug)]
pub struct Report(Vec<History>);

impl Report {
/// Returns the sum of all the next values in the Reports Histories
pub fn get_next_values_sum(&self) -> Value {
self.0.iter().map(|history| history.calculate_next_value()).sum()
}

/// Returns the sum of all the previous values in the Reports Histories
pub fn get_prev_values_sum(&self) -> Value {
self.0.iter().map(|history| history.calculate_prev_value()).sum()
}

/// Checks if the report is empty (No histories)
fn is_empty(&self) -> bool {
self.0.is_empty()
}
}

impl FromStr for Report {
type Err = OasisError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.lines().map(History::from_str).collect::<Result<_, _>>()?))
let report = Self(s.lines().map(History::from_str).collect::<Result<_, _>>()?);

if report.is_empty() {
return Err(OasisError::NoHistories);
}

Ok(report)
}
}

Expand Down Expand Up @@ -139,6 +161,12 @@ mod tests {
assert_eq!(sum, -2);
}

#[test]
#[should_panic]
fn empty_test() {
Report::from_str("").expect("Failed to parse");
}

#[test]
fn solution_1() {
let report = Report::from_str(EXAMPLE_1).expect("Failed to parse");
Expand Down

0 comments on commit 1ae3445

Please sign in to comment.