advent-of-code/2022/src/day_09.rs
2022-12-10 08:53:11 -05:00

142 lines
4.0 KiB
Rust

use std::collections::HashSet;
use Direction::*;
#[derive(Debug)]
enum Direction {
L,
R,
U,
D,
}
#[derive(Debug)]
struct Instruction {
direction: Direction,
steps: i32,
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
struct Location {
x: i32,
y: i32,
}
type Data = Vec<Instruction>;
type Output = usize;
fn parse(input: &str) -> Data {
input
.lines()
.map(|line| {
let (direction, steps) = line.split_once(' ').unwrap();
Instruction {
direction: match direction {
"L" => L,
"R" => R,
"D" => D,
"U" => U,
_ => panic!("expected L, R, D, or U. got {}", direction),
},
steps: steps.parse().unwrap(),
}
})
.collect()
}
fn part_one(data: Data) -> Output {
let mut locations = HashSet::<Location>::new();
let mut head = Location { x: 0, y: 0 };
let mut tail = head;
locations.insert(tail);
for instr in data {
for _ in 0..instr.steps {
// println!("{:?}", tail);
match instr.direction {
L => {
head.x -= 1;
if tail.x == head.x + 2 {
tail.x = head.x + 1;
tail.y = head.y;
}
}
R => {
head.x += 1;
if tail.x == head.x - 2 {
tail.x = head.x - 1;
tail.y = head.y;
}
}
U => {
head.y += 1;
if tail.y + 2 == head.y {
tail.x = head.x;
tail.y = head.y - 1;
}
}
D => {
head.y -= 1;
if tail.y == head.y + 2 {
tail.x = head.x;
tail.y = head.y + 1;
}
}
}
locations.insert(tail);
}
}
locations.len()
}
fn part_two(data: Data) -> Output {
let mut locations = HashSet::<Location>::new();
let mut rope = [Location { x: 0, y: 0 }; 10];
locations.insert(rope[9]);
for instr in data {
for _ in 0..instr.steps {
match instr.direction {
L => {
rope[0].x -= 1;
}
R => {
rope[0].x += 1;
}
U => {
rope[0].y += 1;
}
D => {
rope[0].y -= 1;
}
}
for i in 1..rope.len() {
if rope[i].x.abs_diff(rope[i - 1].x) == 2 && rope[i].y.abs_diff(rope[i - 1].y) == 2
{
rope[i] = Location {
x: rope[i - 1].x + if rope[i - 1].x > rope[i].x { -1 } else { 1 },
y: rope[i - 1].y + if rope[i - 1].y > rope[i].y { -1 } else { 1 },
};
} else if rope[i].x >= rope[i - 1].x + 2 {
rope[i].x = rope[i - 1].x + 1;
rope[i].y = rope[i - 1].y;
} else if rope[i].y >= rope[i - 1].y + 2 {
rope[i].x = rope[i - 1].x;
rope[i].y = rope[i - 1].y + 1;
} else if rope[i].y <= rope[i - 1].y - 2 {
rope[i].x = rope[i - 1].x;
rope[i].y = rope[i - 1].y - 1;
} else if rope[i].x <= rope[i - 1].x - 2 {
rope[i].x = rope[i - 1].x - 1;
rope[i].y = rope[i - 1].y;
}
}
locations.insert(rope[rope.len() - 1]);
}
}
locations.len()
}
advent_of_code_macro::generate_tests!(
day 9,
parse,
part_one,
part_two,
sample tests [88, 36],
star tests [6337, 2455]
);