day 9
This commit is contained in:
parent
a9f0f93558
commit
7e626035f7
163
src/days/day9.rs
Normal file
163
src/days/day9.rs
Normal 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)
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ mod days {
|
||||||
mod day6;
|
mod day6;
|
||||||
mod day7;
|
mod day7;
|
||||||
mod day8;
|
mod day8;
|
||||||
|
mod day9;
|
||||||
}
|
}
|
||||||
|
|
||||||
aoc_lib! { year = 2022 }
|
aoc_lib! { year = 2022 }
|
||||||
|
|
Loading…
Reference in a new issue