1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
use std::ops::AddAssign;
type Scalar = isize;
#[derive(Copy, Clone, Debug)]
enum Instruction
{
Forward(Scalar),
Down(Scalar),
Up(Scalar),
}
#[derive(Copy, Clone, Debug)]
struct Victor
{
x: Scalar,
y: Scalar,
}
fn part1(instructions: &[Instruction])
{
let directions: Vec<Victor> = instructions
.iter()
.map(|&i| Victor::from_direct_instruction(i))
.collect();
let mut position = Victor::new(0, 0);
for dir in directions {
position += dir;
}
println!("Solution to part 1: {}", position.x * position.y);
}
fn part2(instructions: &[Instruction])
{
let mut aim: Scalar = 0;
let mut position = Victor::new(0, 0);
for i in instructions {
match &i {
Instruction::Down(amount) => aim += amount,
Instruction::Up(amount) => aim -= amount,
Instruction::Forward(amount) => position += Victor::new(*amount, amount * aim),
}
}
println!("Solution to part 2: {}", position.x * position.y);
}
pub fn run(input: Vec<String>)
{
let instructions: Vec<Instruction> = input
.into_iter()
.map(|s| Instruction::from_str(s))
.collect();
part1(&instructions);
part2(&instructions);
}
impl Instruction
{
pub fn from_str<S>(instruction_str: S) -> Self
where
S: AsRef<str>,
{
let parts: Vec<&str> = instruction_str.as_ref().split_whitespace().collect();
assert_eq!(parts.len(), 2);
let scalar = parts[1].parse().expect("Not a valid length");
match parts[0] {
"forward" => Self::Forward(scalar),
"down" => Self::Down(scalar),
"up" => Self::Up(scalar),
o => panic!("{} is not a valid instruction", o),
}
}
}
impl Victor
{
pub fn new(x: Scalar, y: Scalar) -> Self { Self { x, y } }
pub fn from_direct_instruction(instruction: Instruction) -> Self
{
use Instruction::*;
match instruction {
Forward(distance) => Victor::new(distance, 0),
Down(distance) => Victor::new(0, distance),
Up(distance) => Victor::new(0, -distance),
}
}
}
impl AddAssign for Victor
{
fn add_assign(&mut self, rhs: Self)
{
self.x += rhs.x;
self.y += rhs.y;
}
}
|