Last active
June 26, 2023 20:16
-
-
Save Philogy/2152684a634ca08b1da51803c69ae23c to your computer and use it in GitHub Desktop.
Advent of Code 2022 (Day 2) in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::cmp::{Ordering, PartialOrd}; | |
use std::fs; | |
#[derive(Debug, PartialEq, Eq, Clone)] | |
enum Move { | |
Rock, | |
Paper, | |
Scissors, | |
} | |
impl Move { | |
fn get_winning_move(&self) -> Move { | |
match self { | |
Move::Rock => Move::Paper, | |
Move::Paper => Move::Scissors, | |
Move::Scissors => Move::Rock, | |
} | |
} | |
fn get_losing_move(&self) -> Move { | |
match self { | |
Move::Rock => Move::Scissors, | |
Move::Paper => Move::Rock, | |
Move::Scissors => Move::Paper, | |
} | |
} | |
fn play_value(&self) -> i32 { | |
match self { | |
Move::Rock => 1, | |
Move::Paper => 2, | |
Move::Scissors => 3, | |
} | |
} | |
fn score_game(&self, opposing_move: &Move) -> i32 { | |
match self.partial_cmp(opposing_move).unwrap() { | |
Ordering::Equal => 3, | |
Ordering::Greater => 6, | |
Ordering::Less => 0, | |
} | |
} | |
fn score_whole(&self, opposing_move: &Move) -> i32 { | |
self.play_value() + self.score_game(opposing_move) | |
} | |
fn parse_opponent(mv: &str) -> Result<Move, String> { | |
match mv { | |
"A" => Ok(Move::Rock), | |
"B" => Ok(Move::Paper), | |
"C" => Ok(Move::Scissors), | |
_ => Err(format!("Failed to parse opponent move '{mv}'")), | |
} | |
} | |
fn parse_naive(mv: &str) -> Result<Move, String> { | |
match mv { | |
"X" => Ok(Move::Rock), | |
"Y" => Ok(Move::Paper), | |
"Z" => Ok(Move::Scissors), | |
_ => Err(format!("Failed to parse naive move '{mv}'")), | |
} | |
} | |
} | |
impl PartialOrd for Move { | |
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | |
Some(if self.get_losing_move() == *other { | |
Ordering::Greater | |
} else if self.get_winning_move() == *other { | |
Ordering::Less | |
} else { | |
Ordering::Equal | |
}) | |
} | |
} | |
fn evaluate_strategy( | |
input: &String, | |
strategy: fn(&str, &Move) -> Result<Move, String>, | |
) -> Result<i32, String> { | |
Ok(input | |
.lines() | |
.map(|line| { | |
let parts = line.split_whitespace().collect::<Vec<&str>>(); | |
let opponent_move = Move::parse_opponent(parts[0])?; | |
let my_move = strategy(parts[1], &opponent_move)?; | |
Ok(my_move.score_whole(&opponent_move)) | |
}) | |
.collect::<Result<Vec<i32>, String>>()? | |
.iter() | |
.sum()) | |
} | |
/// # Advent Of Code (2022 Day 2) [link](https://adventofcode.com/2022/day/2). | |
/// | |
/// Challenge is you receive an input which represents a transcript of Rock-Paper-Scissors Games: | |
/// | |
/// ``` | |
/// A X game 1 | |
/// B Z game 2 | |
/// C Z ... | |
/// B Z | |
/// B Z | |
/// A Y | |
/// A Y | |
/// A Z | |
/// A Y | |
/// ``` | |
/// | |
/// Your opponent's moves are encoded as A, B, C for Rock, Paper and Scissors respectively. Games | |
/// are scored, 6 for a win, 3 for a tie and 0 for a loss. Your choice gives you an additional 1, | |
/// 2 or 3 points for Rock, Paper and Scissors respectively. | |
/// | |
/// ## Part 1 | |
/// | |
/// Your strategy is to interpret X, Y and Z as moves directly whereby they represent Rock, Paper, | |
/// Scissors respectively. This is labeled the "naive" strategy in the code below. You must then compute | |
/// the total score for your strategy across all games. | |
/// | |
/// ## Part 2 | |
/// | |
/// In this part your strategy is to go for a loss at 'X', a tie at 'Y' and a win at 'Z'. For the | |
/// second part you're also meant to compute the total score across all games, this strategy is | |
/// labeled the "actual" strategy in the code below. | |
/// | |
fn main() { | |
let input = fs::read_to_string("./src/input.txt").unwrap(); | |
match evaluate_strategy(&input, |move_str, _| Move::parse_naive(move_str)) { | |
Ok(score_naive) => println!("Naive score: {score_naive}"), | |
Err(err) => println!("Error occured while evaluating naive strategy: {err:?}"), | |
} | |
match evaluate_strategy(&input, |move_str, opponent_move| match move_str { | |
"X" => Ok(opponent_move.get_losing_move()), | |
"Y" => Ok(opponent_move.clone()), | |
"Z" => Ok(opponent_move.get_winning_move()), | |
_ => Err(format!("Failed to parse move '{move_str}'")), | |
}) { | |
Ok(score_actual) => println!("Actual score: {score_actual}"), | |
Err(err) => println!("Error occured while evaluating actual strategy: {err:?}"), | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment