Files
advent-of-code-2022/src/day_2.rs

134 lines
3.1 KiB
Rust
Raw Normal View History

2022-12-03 08:53:34 +00:00
#[derive(Debug)]
enum Error {
InvalidMove,
InvalidOutcome,
}
#[derive(Clone, PartialEq)]
enum Move {
Rock,
Paper,
Scissors
}
impl Move {
fn from_str(input: &str) -> Result<Self, Error> {
match input {
"A"|"X" => Ok(Self::Rock),
"B"|"Y" => Ok(Self::Paper),
"C"|"Z" => Ok(Self::Scissors),
_ => Err(Error::InvalidMove)
}
}
fn beats(&self) -> Move {
match self {
Move::Rock => Move::Scissors,
Move::Paper => Move::Rock,
Move::Scissors => Move::Paper,
}
}
fn is_beaten_by(&self) -> Move {
match self {
Move::Rock => Move::Paper,
Move::Paper => Move::Scissors,
Move::Scissors => Move::Rock,
}
}
/// I don't really know why, but these moves have different scores
fn score(&self) -> u64 {
match self {
Move::Rock => 1,
Move::Paper => 2,
Move::Scissors => 3,
}
}
}
enum Outcome {
Win,
Draw,
Lose,
}
impl Outcome {
pub fn from_str(input: &str) -> Result<Self, Error> {
match input {
"X" => Ok(Self::Lose),
"Y" => Ok(Self::Draw),
"Z" => Ok(Self::Win),
_ => Err(Error::InvalidOutcome)
}
}
}
fn play(player: Move, opponent: Move) -> Outcome {
if player.beats() == opponent {
Outcome::Win
} else if player == opponent {
Outcome::Draw
} else {
Outcome::Lose
}
}
/// decrypt a rock-paper-scissors strategy guide, run through it and calculate the outcome
pub fn part_1(input: &str) -> u64 {
let mut score = 0;
let throws = input.lines();
for throw in throws {
let mut throw: Vec<&str> = throw.split_whitespace().take(2).collect();
let player = Move::from_str(throw.pop().unwrap()).unwrap();
let opponent = Move::from_str(throw.pop().unwrap()).unwrap();
score += player.score();
match play(player, opponent) {
Outcome::Win => {
score += 6;
}
Outcome::Draw => {
score += 3;
}
Outcome::Lose => {}
}
}
score
}
/// decrypt a rock-paper-scissors strategy guide, run through it and calculate the outcome
pub fn part_2(input: &str) -> u64 {
let mut score = 0;
let throws = input.lines();
for throw in throws {
let mut throw: Vec<&str> = throw.split_whitespace().take(2).collect();
let player = throw.pop().unwrap();
let opponent = Move::from_str(throw.pop().unwrap()).unwrap();
let player = match Outcome::from_str(player).unwrap() {
Outcome::Win => opponent.is_beaten_by(),
Outcome::Draw => opponent.clone(),
Outcome::Lose => opponent.beats(),
};
score += player.score();
match play(player, opponent) {
Outcome::Win => {
score += 6;
}
Outcome::Draw => {
score += 3;
}
Outcome::Lose => {}
}
}
score
}