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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
use aoc_runner_derive::*;
use std::str::FromStr;
use std::error::Error;
use std::ops::Add;
use std::iter::Sum;
enum Direction {
Forward,
Up,
Down,
Back,
}
pub struct Command {
direction : Direction,
amount : u32
}
#[derive(Debug)]
pub struct CommandError(String);
impl std::fmt::Display for CommandError {
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f,"Invalid Input: {}",self.0)
}
}
impl Error for CommandError {}
struct Movement {
x : i32,
y : i32,
}
impl Add for Movement{
type Output = Movement;
fn add(self, other : Movement) -> Movement {
Movement{x : self.x + other.x, y : self.y + other.y}
}
}
impl Sum for Movement{
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold(Movement{x:0,y:0},|x,y| x+y)
}
}
impl From<&Command> for Movement {
fn from(c: &Command) -> Self {
match c.direction {
Direction::Forward => { Movement{x : c.amount as i32, y : 0} }
Direction::Up => { Movement{x : 0, y : -(c.amount as i32)}}
Direction::Down => { Movement{x :0, y : c.amount as i32}}
Direction::Back => { Movement{x : -(c.amount as i32), y : 0} }
}
}
}
enum ReinterpretedCommand {
Move(i32),
ChangeAim(i32),
}
impl From<&Command> for ReinterpretedCommand {
fn from(c: &Command) -> Self {
match c.direction {
Direction::Forward => { ReinterpretedCommand::Move(c.amount as i32)}
Direction::Up => { ReinterpretedCommand::ChangeAim(-(c.amount as i32))}
Direction::Down => { ReinterpretedCommand::ChangeAim(c.amount as i32)}
Direction::Back => {ReinterpretedCommand::Move(-(c.amount as i32))}
}
}
}
struct MovementWithDirection {
x : i32,
y : i32,
aim : i32,
}
impl Add<ReinterpretedCommand> for MovementWithDirection {
type Output = Self;
fn add(self, command : ReinterpretedCommand) -> Self {
match command {
ReinterpretedCommand::Move(distance) => {
MovementWithDirection{
x: self.x + distance,
y: self.y + self.aim * distance,
aim : self.aim,
}
}
ReinterpretedCommand::ChangeAim(delta) => {
MovementWithDirection {
x: self.x,
y: self.y,
aim : self.aim + delta,
}
}
}
}
}
impl FromStr for Command {
type Err = CommandError;
fn from_str(s: &str) -> Result<Self, CommandError> {
let mut parts = s.split(" ");
let direction = match parts.next() {
Some("down") => { Some(Direction::Down) }
Some("up") => { Some(Direction::Up) }
Some("forward") => { Some(Direction::Forward) }
Some("back") => { Some(Direction::Back) }
None | Some(_) => { None }
};
let amount = parts.next().map(|ss| FromStr::from_str(ss).ok()).flatten();
direction.zip(amount)
.map(|(direction, amount)| Command{direction,amount})
.ok_or_else(||{ CommandError(String::from(s)) })
}
}
#[aoc_generator(day2)]
pub fn input_generator<'c>(input : &'c str) -> Vec<Command>{
input.lines().map(Command::from_str).map(Result::unwrap).collect()
}
#[aoc(day2, part1)]
pub fn solve_part1(input : &Vec<Command>) -> i32 {
let target : Movement = input.iter().map(From::from).sum();
target.x*target.y
}
#[aoc(day2, part2)]
pub fn solve_part2(input : &Vec<Command>) -> i32 {
let target = input.iter()
.map(From::from)
.fold(MovementWithDirection{x:0,y:0,aim:0},Add::add);
target.x*target.y
}
|