2022 rust day 9
This commit is contained in:
parent
26881d0a81
commit
e604c007ca
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
|
||||||
|
@ -19,45 +20,48 @@ struct Move {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn fix_tail(head: (i32, i32), tail: (i32, i32), direction: &Direction) -> Option<(i32, i32)> {
|
#[inline(always)]
|
||||||
let diff_x = head.0.abs_diff(tail.0);
|
fn fix_tail(head: (i32, i32), tail: (i32, i32)) -> (i32, i32) {
|
||||||
let diff_y = head.1.abs_diff(tail.1);
|
let diff_x = tail.0 - head.0;
|
||||||
match (diff_y > 1, diff_x > 1, direction) {
|
let diff_y = tail.1 - head.1;
|
||||||
(true, _, Direction::U) => Some((head.0, head.1 - 1)),
|
match (diff_x.abs() > 1, diff_y.abs() > 1) {
|
||||||
(true, _, Direction::D) => Some((head.0, head.1 + 1)),
|
(true, true) => (head.0 + diff_x.signum(), head.1 + diff_y.signum()),
|
||||||
(_, true, Direction::L) => Some((head.0 + 1, head.1)),
|
(true, false) => (head.0 + diff_x.signum(), head.1),
|
||||||
(_, true, Direction::R) => Some((head.0 - 1, head.1)),
|
(false, true) => (head.0, head.1 + diff_y.signum()),
|
||||||
(_, _, _) => None,
|
_ => tail,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tail_visits(data: &[Move]) -> HashSet<(i32, i32)> {
|
fn tail_visits(data: &[Move], knots: &mut [(i32, i32)]) -> HashSet<(i32, i32)> {
|
||||||
let mut set = HashSet::from([(0, 0)]);
|
let mut set = HashSet::from([*knots.last().unwrap()]);
|
||||||
let mut head = (0, 0);
|
|
||||||
let mut tail = (0, 0);
|
|
||||||
for m in data {
|
for m in data {
|
||||||
for _ in 0..m.units {
|
for _ in 0..m.units {
|
||||||
match m.direction {
|
// First move the head
|
||||||
Direction::U => head = (head.0, head.1 + 1),
|
let head = knots[0];
|
||||||
Direction::D => head = (head.0, head.1 - 1),
|
knots[0] = match m.direction {
|
||||||
Direction::L => head = (head.0 - 1, head.1),
|
Direction::U => (head.0, head.1 + 1),
|
||||||
Direction::R => head = (head.0 + 1, head.1),
|
Direction::D => (head.0, head.1 - 1),
|
||||||
}
|
Direction::L => (head.0 - 1, head.1),
|
||||||
if let Some(new) = fix_tail(head, tail, &m.direction) {
|
Direction::R => (head.0 + 1, head.1),
|
||||||
set.insert(new);
|
};
|
||||||
tail = new
|
// Second fix all knots sequentially for arbitrary number of knots
|
||||||
|
for idx in 1..knots.len() {
|
||||||
|
knots[idx] = fix_tail(knots[idx-1], knots[idx]);
|
||||||
}
|
}
|
||||||
|
set.insert(*knots.last().unwrap());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve1(data: &[Move]) -> usize {
|
fn solve1(data: &[Move]) -> usize {
|
||||||
tail_visits(&data).len()
|
let mut knots = [(0, 0); 2];
|
||||||
|
tail_visits(&data, &mut knots).len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve2(data: &[Move]) -> i32 {
|
fn solve2(data: &[Move]) -> usize {
|
||||||
2
|
let mut knots = [(0, 0); 10];
|
||||||
|
tail_visits(&data, &mut knots).len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,17 +88,17 @@ fn parse_data<T: AsRef<str>>(data: &[T]) -> Vec<Move> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
static DATA: &[&str; 8] = &["R 4", "U 4", "L 3", "D 1", "R 4", "D 1", "L 5", "R 2"];
|
static DATA_A: &[&str; 8] = &["R 4", "U 4", "L 3", "D 1", "R 4", "D 1", "L 5", "R 2"];
|
||||||
|
static DATA_B: &[&str; 8] = &["R 5", "U 8", "L 8", "D 3", "R 17", "D 10", "L 25", "U 20"];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn part1() {
|
fn part1() {
|
||||||
let data = parse_data(DATA);
|
assert_eq!(13, solve1(&parse_data(DATA_A)));
|
||||||
assert_eq!(13, solve1(&data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn part2() {
|
fn part2() {
|
||||||
let data = parse_data(DATA);
|
assert_eq!(1, solve2(&parse_data(DATA_A)));
|
||||||
assert_eq!(2, solve2(&data));
|
assert_eq!(36, solve2(&parse_data(DATA_B)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue