2023 day9/rust: add solution
This commit is contained in:
parent
c1ceef4afd
commit
91f1c1b609
4 changed files with 121 additions and 0 deletions
10
2023/day9/rust/Cargo.toml
Normal file
10
2023/day9/rust/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "rust_2023_09"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
aoc = { path = "../../../common/rust" }
|
||||
itertools = "0.12.0"
|
102
2023/day9/rust/src/main.rs
Normal file
102
2023/day9/rust/src/main.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
#![warn(clippy::pedantic)]
|
||||
|
||||
use std::{collections::VecDeque, io::stdin};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
type Value = isize;
|
||||
|
||||
fn make_derivative(xs: &[Value]) -> Option<VecDeque<Value>> {
|
||||
if xs.iter().all_equal() {
|
||||
None
|
||||
} else {
|
||||
Some(xs.iter().tuple_windows().map(|(a, b)| b - a).collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Direction {
|
||||
Forward,
|
||||
Backward,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct History {
|
||||
values: VecDeque<Value>,
|
||||
derivatives: Vec<VecDeque<Value>>,
|
||||
}
|
||||
|
||||
impl History {
|
||||
pub fn new(values: VecDeque<Value>) -> Self {
|
||||
let derivatives = std::iter::successors(Some(values.clone()), |prev| {
|
||||
let (s1, s2) = prev.as_slices();
|
||||
assert!(s2.is_empty());
|
||||
make_derivative(s1)
|
||||
})
|
||||
.skip(1)
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
values,
|
||||
derivatives,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand(&mut self, direction: Direction) {
|
||||
Self::expand_values(&mut self.values, &mut self.derivatives, direction);
|
||||
}
|
||||
|
||||
fn expand_values(
|
||||
values: &mut VecDeque<Value>,
|
||||
derivatives: &mut [VecDeque<Value>],
|
||||
direction: Direction,
|
||||
) {
|
||||
if !derivatives.is_empty() {
|
||||
let (next_values, next_derivatives) = derivatives.split_first_mut().unwrap();
|
||||
Self::expand_values(next_values, next_derivatives, direction);
|
||||
}
|
||||
|
||||
match direction {
|
||||
Direction::Forward => {
|
||||
let derivative = derivatives.first().map_or(0, |d| *d.back().unwrap());
|
||||
values.push_back(*values.back().unwrap() + derivative);
|
||||
}
|
||||
Direction::Backward => {
|
||||
let derivative = derivatives.first().map_or(0, |d| *d.front().unwrap());
|
||||
values.push_front(*values.front().unwrap() - derivative);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut histories: VecDeque<_> = stdin()
|
||||
.lines()
|
||||
.map(Result::unwrap)
|
||||
.map(|l| History::new(l.split(' ').map(|n| n.parse().unwrap()).collect()))
|
||||
.collect();
|
||||
|
||||
for history in &mut histories {
|
||||
history.expand(Direction::Forward);
|
||||
}
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
histories
|
||||
.iter()
|
||||
.map(|h| h.values.back().unwrap())
|
||||
.sum::<Value>()
|
||||
);
|
||||
|
||||
for history in &mut histories {
|
||||
history.expand(Direction::Backward);
|
||||
}
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
histories
|
||||
.iter()
|
||||
.map(|h| h.values.front().unwrap())
|
||||
.sum::<Value>()
|
||||
);
|
||||
}
|
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -679,6 +679,14 @@ dependencies = [
|
|||
"petgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust_2023_09"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aoc",
|
||||
"itertools 0.12.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
|
|
|
@ -34,4 +34,5 @@ members = [
|
|||
"2023/day6/rust",
|
||||
"2023/day7/rust",
|
||||
"2023/day8/rust",
|
||||
"2023/day9/rust",
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue