139 lines
3.7 KiB
Rust
139 lines
3.7 KiB
Rust
use super::Solution;
|
|
|
|
pub struct Day09 {}
|
|
|
|
impl Solution for Day09 {
|
|
fn part1(
|
|
&self,
|
|
input: &mut Vec<String>,
|
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
|
let series_collection = self.get_series(input)?;
|
|
Ok(Box::new(self.sum_extrapolated(&series_collection, true)?))
|
|
}
|
|
|
|
fn part2(
|
|
&self,
|
|
input: &mut Vec<String>,
|
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
|
let series_collection = self.get_series(input)?;
|
|
Ok(Box::new(self.sum_extrapolated(&series_collection, false)?))
|
|
}
|
|
|
|
fn get_day(&self) -> u8 {
|
|
9
|
|
}
|
|
}
|
|
|
|
impl Day09 {
|
|
/// Takes a vec of strings and returns a Vec of series of numbers
|
|
fn get_series(&self, input: &Vec<String>) -> Result<Vec<Vec<i32>>, Box<dyn std::error::Error>> {
|
|
let mut series = vec![];
|
|
for s in input.iter() {
|
|
series.push(
|
|
s.split_whitespace()
|
|
.map(|n| n.parse::<i32>().unwrap())
|
|
.collect(),
|
|
);
|
|
}
|
|
Ok(series)
|
|
}
|
|
|
|
/// Returns the sum ov extrapolated values either to the left or the right of the initial series
|
|
fn sum_extrapolated(
|
|
&self,
|
|
series_collection: &Vec<Vec<i32>>,
|
|
forwards: bool,
|
|
) -> Result<i32, Box<dyn std::error::Error>> {
|
|
let mut ans = 0i32;
|
|
|
|
for series in series_collection {
|
|
let mut differences = vec![series.clone()];
|
|
|
|
// Keep finding differences until we have a consistent difference of 0
|
|
while differences
|
|
.last()
|
|
.unwrap()
|
|
.iter()
|
|
.map(|v| v.abs())
|
|
.sum::<i32>()
|
|
!= 0i32
|
|
{
|
|
differences.push(
|
|
differences
|
|
.last()
|
|
.unwrap()
|
|
.windows(2)
|
|
.map(|w| w[1] - w[0])
|
|
.collect::<Vec<i32>>(),
|
|
);
|
|
}
|
|
|
|
if forwards {
|
|
// Sum all of the last values in each row to get next num
|
|
ans += differences
|
|
.iter()
|
|
.map(|s| *s.last().unwrap())
|
|
.collect::<Vec<i32>>()
|
|
.iter()
|
|
.sum::<i32>();
|
|
} else {
|
|
// Scale backwards down the heap to find the previous number in each sequence
|
|
let mut next = 0i32;
|
|
differences
|
|
.iter()
|
|
.rev()
|
|
.map(|s| *s.first().unwrap())
|
|
.collect::<Vec<i32>>()
|
|
.iter()
|
|
.for_each(|v| {
|
|
next = v - next;
|
|
});
|
|
ans += next;
|
|
}
|
|
}
|
|
|
|
Ok(ans)
|
|
}
|
|
}
|
|
|
|
/// Test from puzzle input
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use crate::*;
|
|
|
|
#[test]
|
|
fn part1() {
|
|
let challenge = day09::Day09 {};
|
|
|
|
//Complete the Challenge
|
|
let answer = challenge
|
|
.part1(
|
|
utils::get_input(challenge.get_day(), utils::InputType::Test1)
|
|
.unwrap()
|
|
.as_mut(),
|
|
)
|
|
.unwrap()
|
|
.to_string();
|
|
|
|
assert_eq!(answer, "114");
|
|
}
|
|
|
|
#[test]
|
|
fn part2() {
|
|
let challenge = day09::Day09 {};
|
|
|
|
//Complete the Challenge
|
|
let answer = challenge
|
|
.part2(
|
|
utils::get_input(challenge.get_day(), utils::InputType::Test2)
|
|
.unwrap()
|
|
.as_mut(),
|
|
)
|
|
.unwrap()
|
|
.to_string();
|
|
|
|
assert_eq!(answer, "2");
|
|
}
|
|
}
|