diff --git a/src/bin/p02.rs b/src/bin/p02.rs index 6b4e004..1fb826b 100644 --- a/src/bin/p02.rs +++ b/src/bin/p02.rs @@ -1,8 +1,7 @@ use num_derive::FromPrimitive; use num_traits::FromPrimitive; -use std::cmp::Ordering; use std::fs; -use std::io::{self, BufRead, Seek, Read}; +use std::io::{self, BufRead, Read, Seek}; use std::str::FromStr; #[derive(Clone, Copy, Debug, PartialEq, Eq, FromPrimitive)] @@ -25,48 +24,36 @@ impl FromStr for Rps { } } -impl Ord for Rps { - fn cmp(&self, other: &Self) -> Ordering { +impl Rps { + fn versus(self, other: Self) -> Outcome { match (self, other) { - (x, y) if x == y => Ordering::Equal, + (x, y) if x == y => Outcome::Draw, (Rps::Rock, Rps::Scissors) | (Rps::Paper, Rps::Rock) | (Rps::Scissors, Rps::Paper) => { - Ordering::Greater + Outcome::Win } - _ => Ordering::Less, + _ => Outcome::Lose, } } -} -impl PartialOrd for Rps { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Rps { fn score(self, theirs: Rps) -> u32 { self as u32 + 1 - + match self.cmp(&theirs) { - Ordering::Greater => 6, - Ordering::Equal => 3, - Ordering::Less => 0, + + match self.versus(theirs) { + Outcome::Win => 6, + Outcome::Draw => 3, + Outcome::Lose => 0, } } - - fn play_against(self, win: bool) -> Rps { - FromPrimitive::from_i8((self as i8 + if win { 1 } else { -1 }).rem_euclid(3)).unwrap() - } } -#[derive(Clone, Copy, Debug)] -enum PlayStrat { +#[derive(Clone, Copy, Debug, PartialEq)] +enum Outcome { Lose, Draw, Win, } -impl FromStr for PlayStrat { +impl FromStr for Outcome { type Err = &'static str; fn from_str(input: &str) -> Result { @@ -74,18 +61,20 @@ impl FromStr for PlayStrat { "X" => Ok(Self::Lose), "Y" => Ok(Self::Draw), "Z" => Ok(Self::Win), - _ => Err("Unknown strategy type!"), + _ => Err("Unknown outcome!"), } } } -impl PlayStrat { +impl Outcome { fn against(self, theirs: Rps) -> Rps { - match self { - Self::Draw => theirs, - Self::Win => theirs.play_against(true), - Self::Lose => theirs.play_against(false), - } + let inc = match self { + Outcome::Win => 1, + Outcome::Lose => -1, + Outcome::Draw => 0, + }; + + FromPrimitive::from_i8((theirs as i8 + inc).rem_euclid(3)).unwrap() } } @@ -122,10 +111,7 @@ fn part1(lines: std::io::Lines<&mut io::BufReader>) { total_score += score; println!( "Line \"{}\" - Theirs: {:?}, Mine: {:?}, score {}", - line, - theirs, - mine, - score, + line, theirs, mine, score, ); } @@ -145,7 +131,7 @@ fn part2(lines: std::io::Lines<&mut io::BufReader>) { let strat = split .next() .expect("Want two items per line") - .parse::() + .parse::() .expect("Can't get my strategy"); let mine = strat.against(theirs); @@ -154,11 +140,7 @@ fn part2(lines: std::io::Lines<&mut io::BufReader>) { total_score += score; println!( "Line \"{}\" - Theirs: {:?}, Strat: {:?}, Mine: {:?}, score {}", - line, - theirs, - strat, - mine, - score, + line, theirs, strat, mine, score, ); } @@ -169,6 +151,16 @@ fn part2(lines: std::io::Lines<&mut io::BufReader>) { mod tests { use super::*; + #[test] + fn rps() { + assert_eq!(Outcome::Win, Rps::Rock.versus(Rps::Scissors)); + assert_eq!(Outcome::Win, Rps::Paper.versus(Rps::Rock)); + assert_eq!(Outcome::Win, Rps::Scissors.versus(Rps::Paper)); + assert_eq!(Outcome::Lose, Rps::Rock.versus(Rps::Paper)); + assert_eq!(Outcome::Lose, Rps::Paper.versus(Rps::Scissors)); + assert_eq!(Outcome::Lose, Rps::Scissors.versus(Rps::Rock)); + } + #[test] fn scores() { assert_eq!(7, Rps::Rock.score(Rps::Scissors)); @@ -177,32 +169,22 @@ mod tests { assert_eq!(6, Rps::Scissors.score(Rps::Scissors)); } - #[test] - fn play_against() { - assert_eq!(Rps::Paper, Rps::Rock.play_against(true)); - assert_eq!(Rps::Scissors, Rps::Paper.play_against(true)); - assert_eq!(Rps::Rock, Rps::Scissors.play_against(true)); - } - #[test] fn strat_to_move() { - assert_eq!(Rps::Paper, PlayStrat::Win.against(Rps::Rock)); - assert_eq!(Rps::Scissors, PlayStrat::Win.against(Rps::Paper)); - assert_eq!(Rps::Rock, PlayStrat::Win.against(Rps::Scissors)); + assert_eq!(Rps::Paper, Outcome::Win.against(Rps::Rock)); + assert_eq!(Rps::Scissors, Outcome::Win.against(Rps::Paper)); + assert_eq!(Rps::Rock, Outcome::Win.against(Rps::Scissors)); - assert_eq!(Rps::Scissors, PlayStrat::Lose.against(Rps::Rock)); - assert_eq!(Rps::Rock, PlayStrat::Lose.against(Rps::Paper)); + assert_eq!(Rps::Scissors, Outcome::Lose.against(Rps::Rock)); + assert_eq!(Rps::Rock, Outcome::Lose.against(Rps::Paper)); - assert_eq!(Rps::Rock, PlayStrat::Draw.against(Rps::Rock)); + assert_eq!(Rps::Rock, Outcome::Draw.against(Rps::Rock)); } #[test] fn part_two_ex() { - assert_eq!(4, PlayStrat::Draw.against(Rps::Rock).score(Rps::Rock)); - assert_eq!(1, PlayStrat::Lose.against(Rps::Paper).score(Rps::Paper)); - assert_eq!( - 7, - PlayStrat::Win.against(Rps::Scissors).score(Rps::Scissors) - ); + assert_eq!(4, Outcome::Draw.against(Rps::Rock).score(Rps::Rock)); + assert_eq!(1, Outcome::Lose.against(Rps::Paper).score(Rps::Paper)); + assert_eq!(7, Outcome::Win.against(Rps::Scissors).score(Rps::Scissors)); } }