summaryrefslogtreecommitdiff
path: root/2022/src/bin/day_20.rs
diff options
context:
space:
mode:
Diffstat (limited to '2022/src/bin/day_20.rs')
-rw-r--r--2022/src/bin/day_20.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/2022/src/bin/day_20.rs b/2022/src/bin/day_20.rs
new file mode 100644
index 0000000..dc4bf4f
--- /dev/null
+++ b/2022/src/bin/day_20.rs
@@ -0,0 +1,91 @@
+use nom::{
+ character::complete::{i64, line_ending},
+ combinator::map,
+ multi::separated_list1,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_20.txt")?;
+ let coordinates = GroveCoordinates::parser(&input).unwrap().1;
+
+ {
+ let mut coordinates_1 = coordinates.clone();
+ coordinates_1.mix();
+ dbg!(coordinates_1.coordinate_sum());
+ }
+
+ {
+ let mut coordinates_2 = coordinates.clone();
+ coordinates_2.decrypt(811589153);
+ dbg!(coordinates_2.coordinate_sum());
+ }
+
+ Ok(())
+}
+
+#[derive(Debug, Clone)]
+struct GroveCoordinates(Vec<CoordinatePoint>);
+
+#[derive(Debug, Clone, Copy)]
+struct CoordinatePoint {
+ val: i64,
+ original_order: usize,
+}
+
+impl GroveCoordinates {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ map(separated_list1(line_ending, i64), |points| {
+ GroveCoordinates(
+ points
+ .into_iter()
+ .enumerate()
+ .map(|(original_order, val)| CoordinatePoint {
+ val,
+ original_order,
+ })
+ .collect(),
+ )
+ })(input)
+ }
+
+ fn decrypt(&mut self, key: i64) {
+ for p in &mut self.0 {
+ p.val *= key;
+ }
+
+ for _ in 0..10 {
+ self.mix();
+ }
+ }
+
+ fn mix(&mut self) {
+ for original_i in 0..self.0.len() {
+ let encrypted_i = self
+ .0
+ .iter()
+ .position(|p| p.original_order == original_i)
+ .unwrap();
+ let to_move = self.0.remove(encrypted_i);
+
+ let mut destination_i = encrypted_i as i64 + to_move.val;
+ destination_i %= self.0.len() as i64;
+ if destination_i < 0 {
+ destination_i += self.0.len() as i64;
+ }
+ self.0.insert(destination_i as usize, to_move);
+ }
+ }
+
+ fn get(&self, i: usize) -> i64 {
+ self.0[i % self.0.len()].val
+ }
+
+ fn coordinate_sum(&self) -> i64 {
+ let zero_position = self.0.iter().position(|p| p.val == 0).unwrap();
+ self.get(zero_position + 1000)
+ + self.get(zero_position + 2000)
+ + self.get(zero_position + 3000)
+ }
+}