Skip to main content

aoc/year2020/
day12.rs

1//! # Rain Risk
2//!
3//! On this problem parsing takes almost all the time, so for maximum speed
4//! a custom parser solves both parts during a single pass over the input bytes
5use crate::util::parse::*;
6use crate::util::point::*;
7
8type Input = (i32, i32);
9
10pub fn parse(input: &str) -> Input {
11    let first = input.bytes().filter(u8::is_ascii_uppercase);
12    let second = input.iter_signed();
13
14    let mut part_one = ORIGIN;
15    let mut part_two = ORIGIN;
16    let mut direction = RIGHT;
17    let mut waypoint = Point::new(10, -1);
18
19    for (command, amount) in first.zip(second) {
20        match command {
21            b'N' => {
22                part_one.y -= amount;
23                waypoint.y -= amount;
24            }
25            b'S' => {
26                part_one.y += amount;
27                waypoint.y += amount;
28            }
29            b'E' => {
30                part_one.x += amount;
31                waypoint.x += amount;
32            }
33            b'W' => {
34                part_one.x -= amount;
35                waypoint.x -= amount;
36            }
37            b'L' => {
38                direction = rotate(direction, 360 - amount);
39                waypoint = rotate(waypoint, 360 - amount);
40            }
41            b'R' => {
42                direction = rotate(direction, amount);
43                waypoint = rotate(waypoint, amount);
44            }
45            b'F' => {
46                part_one += direction * amount;
47                part_two += waypoint * amount;
48            }
49            _ => unreachable!(),
50        }
51    }
52
53    (part_one.manhattan(ORIGIN), part_two.manhattan(ORIGIN))
54}
55
56pub fn part1(input: &Input) -> i32 {
57    input.0
58}
59
60pub fn part2(input: &Input) -> i32 {
61    input.1
62}
63
64fn rotate(point: Point, amount: i32) -> Point {
65    match amount {
66        90 => point.clockwise(),
67        180 => point * -1,
68        270 => point.counter_clockwise(),
69        _ => unreachable!(),
70    }
71}