Day 9
parent
515eff8ef0
commit
7ebb51835c
@ -0,0 +1,131 @@
|
||||
use crate::util::prelude::*;
|
||||
|
||||
static INPUT: &str = include_str!("inputs/day9.txt");
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum Direction {
|
||||
Right,
|
||||
Down,
|
||||
Up,
|
||||
Left,
|
||||
}
|
||||
impl Direction {
|
||||
fn diff(&self) -> (sint, sint) {
|
||||
use Direction::*;
|
||||
|
||||
match self {
|
||||
Right => (1, 0),
|
||||
Up => (0, 1),
|
||||
Down => (0, -1),
|
||||
Left => (-1, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl core::str::FromStr for Direction {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"U" => Direction::Up,
|
||||
"R" => Direction::Right,
|
||||
"L" => Direction::Left,
|
||||
"D" => Direction::Down,
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Move {
|
||||
count: uint,
|
||||
direction: Direction,
|
||||
}
|
||||
impl core::str::FromStr for Move {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut it = s.split(' ');
|
||||
|
||||
let direction = it.next().ok_or(())?.parse()?;
|
||||
let count = it.next().ok_or(())?.parse().map_err(|_| ())?;
|
||||
|
||||
Ok(Self { count, direction })
|
||||
}
|
||||
}
|
||||
|
||||
fn moves(s: &str) -> impl Iterator<Item = Move> + '_ {
|
||||
s.lines()
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.parse().unwrap())
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
struct Pos(sint, sint);
|
||||
|
||||
fn move_tail(head: &Pos, tail: &mut Pos) {
|
||||
let diff_x = head.0 - tail.0;
|
||||
let diff_y = head.1 - tail.1;
|
||||
|
||||
let diff_x_abs = diff_x.abs();
|
||||
let diff_y_abs = diff_y.abs();
|
||||
// diag
|
||||
let mv = if diff_x_abs + diff_y_abs == 3 {
|
||||
(diff_x.signum(), diff_y.signum())
|
||||
} else {
|
||||
((diff_x / 2).signum(), (diff_y / 2).signum())
|
||||
};
|
||||
|
||||
tail.0 += mv.0;
|
||||
tail.1 += mv.1;
|
||||
}
|
||||
|
||||
pub fn part1() {
|
||||
let mut head = Pos(0, 0);
|
||||
let mut tail = Pos(0, 0);
|
||||
|
||||
let moves = moves(INPUT);
|
||||
let mut locations = HashSet::default();
|
||||
|
||||
for mv in moves {
|
||||
let dir = mv.direction.diff();
|
||||
let count = mv.count;
|
||||
|
||||
for _ in 0..count {
|
||||
head.0 += dir.0;
|
||||
head.1 += dir.1;
|
||||
|
||||
move_tail(&head, &mut tail);
|
||||
|
||||
locations.insert(tail);
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", locations.len())
|
||||
}
|
||||
|
||||
pub fn part2() {
|
||||
let mut parts = vec![Pos(0, 0); 10];
|
||||
|
||||
let moves = moves(INPUT);
|
||||
let mut locations = HashSet::default();
|
||||
|
||||
for mv in moves {
|
||||
let dir = mv.direction.diff();
|
||||
let count = mv.count;
|
||||
|
||||
for _ in 0..count {
|
||||
parts[0].0 += dir.0;
|
||||
parts[0].1 += dir.1;
|
||||
|
||||
for i in 0..parts.len() - 1 {
|
||||
let tail: &mut _ =
|
||||
unsafe { core::mem::transmute(&mut parts[i + 1]) };
|
||||
move_tail(&parts[i], tail);
|
||||
}
|
||||
|
||||
locations.insert(*parts.last().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", locations.len())
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue