1use 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}