diff --git a/2022/day9/rust/Cargo.toml b/2022/day9/rust/Cargo.toml new file mode 100644 index 0000000..53f4834 --- /dev/null +++ b/2022/day9/rust/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust_2022_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" } diff --git a/2022/day9/rust/src/main.rs b/2022/day9/rust/src/main.rs new file mode 100644 index 0000000..151dc7a --- /dev/null +++ b/2022/day9/rust/src/main.rs @@ -0,0 +1,115 @@ +#![warn(clippy::pedantic)] + +use std::{ + collections::BTreeSet, + io::{stdin, Read}, + ops::{Add, AddAssign, Sub}, +}; + +use aoc::*; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Vec2 { + x: i32, // increases toward right + y: i32, // increases toward top +} + +impl Vec2 { + #[must_use] + pub fn new(x: i32, y: i32) -> Self { + Self { x, y } + } + + #[must_use] + pub fn map(self, mut f: impl FnMut(i32) -> i32) -> Self { + Self { + x: f(self.x), + y: f(self.y), + } + } +} + +impl Add for Vec2 { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} + +impl AddAssign for Vec2 { + fn add_assign(&mut self, rhs: Self) { + self.x += rhs.x; + self.y += rhs.y; + } +} + +impl Sub for Vec2 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } +} + +impl From<(i32, i32)> for Vec2 { + fn from((x, y): (i32, i32)) -> Self { + Self { x, y } + } +} + +impl From for (i32, i32) { + fn from(v: Vec2) -> Self { + (v.x, v.y) + } +} + +fn get_direction_vec(direction: &str) -> Vec2 { + match direction { + "U" => (0, 1), + "R" => (1, 0), + "D" => (0, -1), + "L" => (-1, 0), + _ => panic!(), + } + .into() +} + +fn main() { + let mut data = String::new(); + stdin().read_to_string(&mut data).unwrap(); + + let mut knots = vec![Vec2::new(0, 0); 10]; + + let mut tail_positions = BTreeSet::new(); + tail_positions.insert(*knots.last().unwrap()); + + for line in data.lines() { + let (direction, distance) = line.split_once(' ').unwrap(); + let distance: usize = distance.parse().unwrap(); + + for _i in 0..distance { + knots[0] += get_direction_vec(direction); + let mut following = knots[0]; + + for knot in &mut knots[1..] { + let delta = match (following - *knot).into() { + (x, y) if x.abs() <= 1 && y.abs() <= 1 => (0, 0), + (x, y) => (x.signum(), y.signum()), + } + .into(); + *knot += delta; + following = *knot; + } + tail_positions.insert(*knots.last().unwrap()); + } + } + + println!("{:?}", tail_positions.len()); +} diff --git a/Cargo.lock b/Cargo.lock index 2712dc6..d8726df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -524,6 +524,13 @@ dependencies = [ "aoc", ] +[[package]] +name = "rust_2022_09" +version = "0.1.0" +dependencies = [ + "aoc", +] + [[package]] name = "ryu" version = "1.0.11" diff --git a/Cargo.toml b/Cargo.toml index 9f1ad8a..8c53cdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,5 @@ members = [ "2022/day6/rust", "2022/day7/rust", "2022/day8/rust", + "2022/day9/rust", ]