/// --- Day 2: Rock Paper Scissors --- /// /// The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the /// snack storage, a giant Rock Paper Scissors tournament is already in progress. /// /// Rock Paper Scissors is a game between two players. Each game contains many rounds; in each /// round, the players each simultaneously choose one of Rock, Paper, or Scissors using a hand /// shape. Then, a winner for that round is selected: Rock defeats Scissors, Scissors defeats /// Paper, and Paper defeats Rock. If both players choose the same shape, the round instead ends /// in a draw. /// /// Appreciative of your help yesterday, one Elf gives you an encrypted strategy guide (your puzzle /// input) that they say will be sure to help you win. "The first column is what your opponent is /// going to play: A for Rock, B for Paper, and C for Scissors. The second column--" Suddenly, the /// Elf is called away to help with someone's tent. /// /// The second column, you reason, must be what you should play in response: X for Rock, Y for /// Paper, and Z for Scissors. Winning every time would be suspicious, so the responses must have /// been carefully chosen. /// /// The winner of the whole tournament is the player with the highest score. Your total score is /// the sum of your scores for each round. The score for a single round is the score for the shape /// you selected (1 for Rock, 2 for Paper, and 3 for Scissors) plus the score for the outcome of /// the round (0 if you lost, 3 if the round was a draw, and 6 if you won). /// /// Since you can't be sure if the Elf is trying to help you or trick you, you should calculate the /// score you would get if you were to follow the strategy guide. /// /// For example, suppose you were given the following strategy guide: /// /// ``` /// A Y /// B X /// C Z /// ``` /// /// This strategy guide predicts and recommends the following: /// /// In the first round, your opponent will choose Rock (A), and you should choose Paper (Y). /// This ends in a win for you with a score of 8 (2 because you chose Paper + 6 because you /// won). /// In the second round, your opponent will choose Paper (B), and you should choose Rock (X). /// This ends in a loss for you with a score of 1 (1 + 0). /// The third round is a draw with both players choosing Scissors, giving you a score of 3 + 3 /// = 6. /// /// In this example, if you were to follow the strategy guide, you would get a total score of 15 (8 /// + 1 + 6). /// /// What would your total score be if everything goes exactly according to your strategy guide? use clap::Parser; use itertools::Itertools; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; use std::path::PathBuf; const FILEPATH: &'static str = "examples/input.txt"; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Cli { #[clap(short, long, default_value = FILEPATH)] file: PathBuf, } #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] enum RockPaperScissorsKind { Rock, Paper, Scissors, } #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] enum GameOutcome { Win, Loss, Draw, } #[derive(Copy, Clone, Debug)] struct GamePrediction { player: RockPaperScissorsKind, opponent: RockPaperScissorsKind, } fn kind_to_value(kind: RockPaperScissorsKind) -> i32 { use RockPaperScissorsKind::*; match kind { Rock => 1, Paper => 2, Scissors => 3, } } fn opp_to_kind(val: char) -> Option { use RockPaperScissorsKind::*; match val { 'A' => Some(Rock), 'B' => Some(Paper), 'C' => Some(Scissors), _ => None, } } fn player_to_kind(val: char) -> Option { use RockPaperScissorsKind::*; match val { 'X' => Some(Rock), 'Y' => Some(Paper), 'Z' => Some(Scissors), _ => None, } } fn outcome_to_value(outcome: GameOutcome) -> i32 { use GameOutcome::*; match outcome { Win => 6, Draw => 3, Loss => 0, } } fn game_pred_to_outcome(prediction: GamePrediction) -> GameOutcome { use GameOutcome::*; use RockPaperScissorsKind::*; match (prediction.player, prediction.opponent) { (Rock, Scissors) => Win, (Scissors, Paper) => Win, (Paper, Rock) => Win, (x, y) if x == y => Draw, _ => Loss, } } fn game_pred_to_value(prediction: GamePrediction) -> i32 { outcome_to_value(game_pred_to_outcome(prediction)) + kind_to_value(prediction.player) } fn main() { let args = Cli::parse(); let file = File::open(&args.file).unwrap(); let reader = BufReader::new(file); let res: i32 = reader .lines() .map(|l| { l.unwrap() .split(' ') .map(|w| w.parse::().unwrap()) .collect_tuple::<(char, char)>() }) .map(|v| v.unwrap()) .map(|(o_char, p_char)| GamePrediction { player: player_to_kind(p_char).unwrap(), opponent: opp_to_kind(o_char).unwrap(), }) .map(|pred| game_pred_to_value(pred)) // .inspect(|x| println!("{x:?}")) .sum(); println!( "The total score if everything goes exactly according to your strategy guide is {}", res ); }