-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path02.rs
118 lines (102 loc) Β· 2.72 KB
/
02.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
107
108
109
110
111
112
113
114
115
116
117
118
use core::fmt::Debug;
use std::str::FromStr;
#[repr(u32)]
#[derive(Clone, Copy, PartialEq)]
// The value is the score for playing the given hand
enum Hand {
Rock = 1,
Paper = 2,
Scissors = 3,
}
impl FromStr for Hand {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
// second part for part 1
"A" | "X" => Ok(Hand::Rock),
"B" | "Y" => Ok(Hand::Paper),
"C" | "Z" => Ok(Hand::Scissors),
_ => Err("Invalid hand".to_owned()),
}
}
}
impl Hand {
fn score_vs(&self, opponent: Hand) -> Score {
if self == &opponent {
Score::Draw
} else if self.wins_against() == opponent {
Score::Win
} else {
Score::Lose
}
}
fn wins_against(&self) -> Hand {
match self {
Hand::Rock => Hand::Scissors,
Hand::Paper => Hand::Rock,
Hand::Scissors => Hand::Paper,
}
}
fn loses_against(&self) -> Hand {
match self {
Hand::Rock => Hand::Paper,
Hand::Paper => Hand::Scissors,
Hand::Scissors => Hand::Rock,
}
}
fn hand_to_play(desired_score: Score, opponent: Hand) -> Hand {
match desired_score {
Score::Draw => opponent,
Score::Win => opponent.loses_against(),
Score::Lose => opponent.wins_against(),
}
}
}
#[repr(u32)]
#[derive(Clone, Copy)]
enum Score {
Lose = 0,
Draw = 3,
Win = 6,
}
impl FromStr for Score {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"X" => Ok(Score::Lose),
"Y" => Ok(Score::Draw),
"Z" => Ok(Score::Win),
_ => Err("Invalid score".to_owned()),
}
}
}
fn play<L: FromStr, R: FromStr>(input: &str, score_fn: &dyn Fn(L, R) -> u32) -> u32
where
<L as FromStr>::Err: Debug,
<R as FromStr>::Err: Debug,
{
input
.lines()
.map(|line| {
let chars: Vec<&str> = line.split(' ').collect();
let l: L = chars[0].parse().unwrap();
let r: R = chars[1].parse().unwrap();
score_fn(l, r)
})
.sum()
}
fn part_one(input: &str) -> u32 {
play(input, &|opponent: Hand, you: Hand| {
you as u32 + you.score_vs(opponent) as u32
})
}
fn part_two(input: &str) -> u32 {
play(input, &|opponent: Hand, planned_score: Score| {
planned_score as u32 + Hand::hand_to_play(planned_score, opponent) as u32
})
}
pub fn main() {
let input = include_str!("../inputs/02.txt");
println!("part one: {}", part_one(input)); // 11666
println!("part two: {}", part_two(input)); // 12767
}