2022-12-09 10:44:26 -06:00
|
|
|
mod common;
|
|
|
|
|
2022-12-09 11:41:04 -06:00
|
|
|
use std::{collections::HashSet, iter::repeat};
|
2022-12-09 10:44:26 -06:00
|
|
|
|
|
|
|
type Input = Vec<(char, i32)>;
|
|
|
|
type Answer = usize;
|
|
|
|
|
|
|
|
fn processed_input(input: &str) -> Input {
|
|
|
|
input
|
|
|
|
.lines()
|
|
|
|
.map(|l| {
|
|
|
|
let mut args = l.split(' ');
|
|
|
|
(
|
|
|
|
args.next().unwrap().chars().next().unwrap(),
|
|
|
|
args.next().unwrap().parse::<i32>().unwrap(),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2022-12-09 11:41:04 -06:00
|
|
|
fn follow((hx, hy): (i32, i32), (tx, ty): (i32, i32)) -> (i32, i32) {
|
|
|
|
let (dx, dy) = (tx.abs_diff(hx), ty.abs_diff(hy));
|
|
|
|
let (mx, my) = ((hx - tx) / 2, (hy - ty) / 2);
|
|
|
|
if dx > 1 && dy > 1 {
|
|
|
|
(tx + mx, ty + my)
|
|
|
|
} else if dx > 1 {
|
|
|
|
(tx + mx, hy)
|
|
|
|
} else if dy > 1 {
|
|
|
|
(hx, ty + my)
|
|
|
|
} else {
|
|
|
|
(tx, ty)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn both_parts(input: &Input) -> (Answer, Answer) {
|
|
|
|
let mut p1: HashSet<(i32, i32)> = HashSet::new();
|
2022-12-09 10:44:26 -06:00
|
|
|
let mut h: (i32, i32) = (0, 0);
|
|
|
|
let mut t: (i32, i32) = (0, 0);
|
|
|
|
|
2022-12-09 11:41:04 -06:00
|
|
|
let mut p2: HashSet<(i32, i32)> = HashSet::new();
|
|
|
|
let mut r: Vec<(i32, i32)> = repeat((0, 0)).take(10).collect();
|
2022-12-09 10:44:26 -06:00
|
|
|
|
|
|
|
for i in input {
|
2022-12-09 11:41:04 -06:00
|
|
|
if let Some((x, y)) = match i.0 {
|
|
|
|
'L' => Some((-1, 0)),
|
|
|
|
'R' => Some((1, 0)),
|
|
|
|
'U' => Some((0, -1)),
|
|
|
|
'D' => Some((0, 1)),
|
|
|
|
_ => None,
|
|
|
|
} {
|
|
|
|
for _ in 0..i.1 {
|
2022-12-09 11:42:37 -06:00
|
|
|
// move part 1 head/tail
|
2022-12-09 11:41:04 -06:00
|
|
|
h = (h.0 + x, h.1 + y);
|
|
|
|
t = follow(h, t);
|
|
|
|
p1.insert(t);
|
|
|
|
|
2022-12-09 11:42:37 -06:00
|
|
|
// move part 2 rope
|
2022-12-09 11:41:04 -06:00
|
|
|
r[0] = (r[0].0 + x, r[0].1 + y);
|
|
|
|
for s in 1..r.len() {
|
|
|
|
r[s] = follow(r[s - 1], r[s]);
|
2022-12-09 10:55:35 -06:00
|
|
|
}
|
2022-12-09 11:41:04 -06:00
|
|
|
p2.insert(r[r.len() - 1]);
|
2022-12-09 10:55:35 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-09 11:41:04 -06:00
|
|
|
(p1.len(), p2.len())
|
2022-12-09 10:44:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let input_text = common::day_input(9);
|
|
|
|
let input = processed_input(&input_text);
|
2022-12-09 11:41:04 -06:00
|
|
|
common::show_both_answers(&both_parts(&input))
|
2022-12-09 10:44:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
const TEST_INPUT: &str = "R 4
|
|
|
|
U 4
|
|
|
|
L 3
|
|
|
|
D 1
|
|
|
|
R 4
|
|
|
|
D 1
|
|
|
|
L 5
|
|
|
|
R 2";
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test() {
|
|
|
|
let input = processed_input(TEST_INPUT);
|
2022-12-09 11:41:04 -06:00
|
|
|
assert_eq!(both_parts(&input), (13, 1));
|
2022-12-09 10:55:35 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
const TEST_INPUT2: &str = "R 5
|
|
|
|
U 8
|
|
|
|
L 8
|
|
|
|
D 3
|
|
|
|
R 17
|
|
|
|
D 10
|
|
|
|
L 25
|
|
|
|
U 20";
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part2_test2() {
|
|
|
|
let input2 = processed_input(TEST_INPUT2);
|
2022-12-09 11:41:04 -06:00
|
|
|
assert_eq!(both_parts(&input2), (88, 36));
|
2022-12-09 10:44:26 -06:00
|
|
|
}
|
|
|
|
}
|