add more code for 54 (WIP)

This commit is contained in:
Dr. Matthias Ratajczak
2022-08-18 16:35:06 +02:00
parent 1dbc0052ca
commit 0b7a440a64
+16 -224
View File
@@ -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<T> {
fn contains_value(&self, x: &T) -> bool;
}
impl Contains<Value> 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
);
}
}