aoc/year2016/
day01.rs

1//! # No Time for a Taxicab
2//!
3//! The solution is short as it leverages three utility classes, [`hash`] for speedy sets,
4//! [`parse`] for extracting integers from surrounding text and [`point`] for two dimensional
5//! rotations and translations.
6//!
7//! [`hash`]: crate::util::hash
8//! [`parse`]: crate::util::parse
9//! [`point`]: crate::util::point
10use crate::util::hash::*;
11use crate::util::parse::*;
12use crate::util::point::*;
13
14type Pair = (u8, i32);
15
16pub fn parse(input: &str) -> Vec<Pair> {
17    let first = input.bytes().filter(u8::is_ascii_uppercase);
18    let second = input.iter_signed();
19    first.zip(second).collect()
20}
21
22pub fn part1(input: &[Pair]) -> i32 {
23    let mut position = ORIGIN;
24    let mut direction = UP;
25
26    for &(turn, amount) in input {
27        direction =
28            if turn == b'L' { direction.counter_clockwise() } else { direction.clockwise() };
29        position += direction * amount;
30    }
31
32    position.manhattan(ORIGIN)
33}
34
35pub fn part2(input: &[Pair]) -> i32 {
36    let mut position = ORIGIN;
37    let mut direction = UP;
38    let mut visited = FastSet::with_capacity(1000);
39
40    for &(turn, amount) in input {
41        direction =
42            if turn == b'L' { direction.counter_clockwise() } else { direction.clockwise() };
43
44        for _ in 0..amount {
45            position += direction;
46            if !visited.insert(position) {
47                return position.manhattan(ORIGIN);
48            }
49        }
50    }
51
52    unreachable!()
53}