-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
106 lines (93 loc) · 2.35 KB
/
main.rs
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
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Shape {
Rock,
Paper,
Scissors,
}
fn shape_score(shape: Shape) -> usize {
match shape {
Shape::Rock => 1,
Shape::Paper => 2,
Shape::Scissors => 3,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Outcome {
Win,
Lose,
Draw,
}
fn outcome_score(outcome: Outcome) -> usize {
match outcome {
Outcome::Win => 6,
Outcome::Draw => 3,
Outcome::Lose => 0,
}
}
fn outcome(me: Shape, opp: Shape) -> Outcome {
use Outcome::*;
if me == opp {
Draw
} else {
match (me, opp) {
(Shape::Rock, Shape::Scissors) => Win,
(Shape::Paper, Shape::Rock) => Win,
(Shape::Scissors, Shape::Paper) => Win,
_ => Lose,
}
}
}
fn parse_shape(s: &str) -> Shape {
match s {
"A" | "X" => Shape::Rock,
"B" | "Y" => Shape::Paper,
"C" | "Z" => Shape::Scissors,
_ => panic!("Invalid shape"),
}
}
fn parse_outcome(s: &str) -> Outcome {
match s {
"Z" => Outcome::Win,
"X" => Outcome::Lose,
"Y" => Outcome::Draw,
_ => panic!("Invalid outcome"),
}
}
fn part1(input: &str) -> usize {
input
.lines()
.map(|line| {
let (opp, me) = line.split_once(' ').unwrap();
let (me, opp) = (parse_shape(me), parse_shape(opp));
shape_score(me) + outcome_score(outcome(me, opp))
})
.sum()
}
fn part2(input: &str) -> usize {
input
.lines()
.map(|line| {
let (opp, expected_outcome) = line.split_once(' ').unwrap();
let opp = parse_shape(opp);
let expected_outcome = parse_outcome(expected_outcome);
let all_shapes = vec![Shape::Rock, Shape::Paper, Shape::Scissors];
let me = *all_shapes
.iter()
.find(|&me| outcome(*me, opp) == expected_outcome)
.unwrap();
shape_score(me) + outcome_score(outcome(me, opp))
})
.sum()
}
fn main() {
println!("Part 1: {:?}", part1(include_str!("in.txt")));
println!("Part 2: {:?}", part2(include_str!("in.txt")));
}
#[test]
fn test_part1() {
assert_eq!(part1(include_str!("test.txt")), 15);
}
#[test]
fn test_part2() {
assert_eq!(part2(include_str!("test.txt")), 12);
}