diff --git a/src/euler54/src/main.rs b/src/euler54/src/main.rs index 1afdfe7..5dac754 100644 --- a/src/euler54/src/main.rs +++ b/src/euler54/src/main.rs @@ -1,237 +1,29 @@ -#![allow(dead_code, unused_imports)] -use std::{ - cmp::max, - collections::{HashMap, HashSet}, -}; +#![allow(dead_code)] -type Cards = [Card; 5]; -type Values = [Value; 5]; - -const ROYAL_FLUSH: [Value; 5] = [ - Value::Ten, - Value::Jack, - Value::Queen, - Value::King, - Value::Ace, -]; +mod card; +mod evaluation; +mod game; +mod hand; +mod suit; +mod value; fn main() { println!("Hello, world!"); } - -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone)] -struct Card { - value: Value, - suit: Suit, -} - -impl Card { - fn from_str(s: &str) -> Self { - assert_eq!(s.len(), 2); - let mut chars = s.chars(); - let value = Value::from_char(chars.next().unwrap()); - let suit = Suit::from_char(chars.next().unwrap()); - Self { value, suit } - } -} - -#[derive(Debug, PartialEq, Hash, Eq, Clone, PartialOrd, Ord)] -enum Suit { - Diamonds, - Hearts, - Spades, - Clubs, -} - -impl Suit { - fn from_char(c: char) -> Self { - match c { - 'D' => Self::Diamonds, - 'H' => Self::Hearts, - 'S' => Self::Spades, - 'C' => Self::Clubs, - _ => panic!(), - } - } -} - -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone)] -enum Value { - Two, - Three, - Four, - Five, - Six, - Seven, - Eight, - Nine, - Ten, - Jack, - Queen, - King, - Ace, -} - -const VALUES: [Value; 13] = [ - Value::Two, - Value::Three, - Value::Four, - Value::Five, - Value::Six, - Value::Seven, - Value::Eight, - Value::Nine, - Value::Ten, - Value::Jack, - Value::Queen, - Value::King, - Value::Ace, -]; - -impl Value { - fn from_char(c: char) -> Self { - match c { - '2' => Self::Two, - '3' => Self::Three, - '4' => Self::Four, - '5' => Self::Five, - '6' => Self::Six, - '7' => Self::Seven, - '8' => Self::Eight, - '9' => Self::Nine, - 'T' => Self::Ten, - 'J' => Self::Jack, - 'Q' => Self::Queen, - 'K' => Self::King, - 'A' => Self::Ace, - _ => panic!("{c}"), - } - } -} - -struct Hand { - cards: [Card; 5], - evaluation: Evaluation, -} - -struct Game { - player1: Hand, - player2: Hand, -} - -#[derive(PartialEq, PartialOrd)] -enum Evaluation { - High, - OnePair, - TwoPair, - ThreeOfAKind, - Straight, - Flush, - FullHouse, - FourOfAKind, - StraightFlush(Card), - RoyalFlush, -} - -impl Game { - fn from_line(line: &str) -> Self { - assert_eq!(line.len(), 29); - let (p1, p2) = Self::divide_into_two_hands(line); - let player1 = Hand::from_line(p1); - let player2 = Hand::from_line(p2); - Self { player1, player2 } - } - - fn divide_into_two_hands(line: &str) -> (&str, &str) { - let (p1, p2) = line.split_at(15); - (&p1[..14], p2) - } -} - -impl Hand { - fn from_line(line: &str) -> Self { - assert_eq!(line.len(), 14); - let vec: Vec<_> = line.split_whitespace().map(Card::from_str).collect(); - let cards: [Card; 5] = vec.try_into().unwrap_or_else(|_| panic!()); - let evaluation = Evaluation::from_cards(&cards); - Self { cards, evaluation } - } -} - -trait Contains { - fn contains_value(&self, x: &T) -> bool; -} - -impl Contains for &Cards { - fn contains_value(&self, x: &Value) -> bool { - for card in self.iter() { - if card.value == *x { - return true; - } - } - false - } -} - -trait CardTrait { - fn have_matching_suits(&self) -> bool; - fn contain_all_values_of(&self, values: &Values) -> bool; - fn get_highest_card(&self) -> Card; - fn have_consecutive_values(&self) -> bool; -} - -impl CardTrait for Cards { - fn have_matching_suits(&self) -> bool { - self[1..] - .iter() - .zip(self[..4].iter()) - .all(|(c1, c2)| c1.suit == c2.suit) - } - - fn contain_all_values_of(&self, values: &Values) -> bool { - values.iter().all(|v| self.contains_value(v)) - } - - fn get_highest_card(&self) -> Card { - self.iter() - .reduce(|accum, item| max(accum, item)) - .unwrap() - .clone() - } - - fn have_consecutive_values(&self) -> bool { - VALUES. - } -} - -impl Evaluation { - fn from_cards(cards: &Cards) -> Self { - if Self::is_royal_flush(cards) { - Self::RoyalFlush - } else if Self::is_straight_flush(cards) { - Self::StraightFlush(cards.get_highest_card()) - } else { - todo!() - } - } - - fn is_straight_flush(cards: &Cards) -> bool { - cards.have_matching_suits() && cards.have_consecutive_values() - } - - fn is_royal_flush(cards: &Cards) -> bool { - cards.have_matching_suits() && cards.contain_all_values_of(&ROYAL_FLUSH) - } -} - #[cfg(test)] mod test { - use crate::{Card, Game}; + use crate::game::{Game, Player as P}; #[test] fn example1() { let line = "5H 5C 6S 7S KD 2C 3S 8S 8D TD"; - let game = Game::from_line(line); - assert_eq!(game.player1.cards[0], Card::from_str("5H")); + let game = Game::from(line); + assert_eq!( + game.winner, + P::Player2, + "player 1: {:#?}\nplayer 2: {:#?}", + game.player1.evaluation, + game.player2.evaluation + ); } }