This commit is contained in:
missing 2022-12-09 20:28:28 -06:00
parent a9f0f93558
commit 7e626035f7
2 changed files with 164 additions and 0 deletions

163
src/days/day9.rs Normal file
View file

@ -0,0 +1,163 @@
use std::{
cmp::Ordering,
collections::HashSet,
ops::{Add, Sub},
};
use aoc_runner_derive::{aoc, aoc_generator};
#[derive(Clone, Copy)]
enum Direction {
Up,
Down,
Left,
Right,
UpLeft,
UpRight,
DownLeft,
DownRight,
}
impl Direction {
fn to_vec2(self) -> Vec2 {
match self {
Direction::Up => (0, 1),
Direction::Down => (0, -1),
Direction::Left => (-1, 0),
Direction::Right => (1, 0),
Direction::UpLeft => (-1, 1),
Direction::UpRight => (1, 1),
Direction::DownLeft => (-1, -1),
Direction::DownRight => (1, -1),
}
.into()
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
struct Vec2 {
x: i32,
y: i32,
}
impl From<(i32, i32)> for Vec2 {
fn from((x, y): (i32, i32)) -> Self {
Self { x, 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 Sub for Vec2 {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
#[aoc_generator(day9)]
fn generator(input: &str) -> Vec<(Direction, u32)> {
input
.lines()
.map(|l| {
(
match l.chars().next().unwrap() {
'U' => Direction::Up,
'D' => Direction::Down,
'L' => Direction::Left,
'R' => Direction::Right,
_ => panic!(),
},
l[2..].parse().unwrap(),
)
})
.collect()
}
fn do_pull(head: Vec2, tail: Vec2) -> Vec2 {
let head_relative_to_tail = head - tail;
if head_relative_to_tail.x.abs() <= 1 && head_relative_to_tail.y.abs() <= 1 {
return tail;
}
use Ordering::*;
let dir_to_move_tail = match (
head_relative_to_tail.x.cmp(&0),
head_relative_to_tail.y.cmp(&0),
) {
(Less, Less) => Direction::DownLeft,
(Less, Equal) => Direction::Left,
(Less, Greater) => Direction::UpLeft,
(Equal, Less) => Direction::Down,
(Equal, Equal) => unreachable!(),
(Equal, Greater) => Direction::Up,
(Greater, Less) => Direction::DownRight,
(Greater, Equal) => Direction::Right,
(Greater, Greater) => Direction::UpRight,
};
tail + dir_to_move_tail.to_vec2()
}
struct Rope<const N: usize> {
inner: [Vec2; N],
}
impl<const N: usize> Rope<N> {
fn new() -> Self {
Self {
inner: [(0, 0).into(); N],
}
}
fn do_move(&mut self, dir: Direction) {
self.inner[0] = self.inner[0] + dir.to_vec2();
for i in 0..N - 1 {
self.inner[i + 1] = do_pull(self.inner[i], self.inner[i + 1]);
}
}
fn tail(&self) -> Vec2 {
*self.inner.last().unwrap()
}
}
fn run_simulation<const N: usize>(input: &[(Direction, u32)]) -> usize {
let mut rope = Rope::<N>::new();
let mut tail_locations = HashSet::new();
tail_locations.insert(rope.tail());
for instruction in input {
for _ in 0..instruction.1 {
rope.do_move(instruction.0);
tail_locations.insert(rope.tail());
}
}
tail_locations.len()
}
#[aoc(day9, part1)]
fn part1_indexing(input: &[(Direction, u32)]) -> usize {
run_simulation::<2>(input)
}
#[aoc(day9, part2)]
fn part2(input: &[(Direction, u32)]) -> usize {
run_simulation::<10>(input)
}

View file

@ -9,6 +9,7 @@ mod days {
mod day6;
mod day7;
mod day8;
mod day9;
}
aoc_lib! { year = 2022 }