Untitled
unknown
rust
8 months ago
2.4 kB
11
Indexable
fn from(mut cards: [crate::Card; 5]) -> Self {
let mut suits = [false; 4];
let mut ranks = [0; 15];
let mut set4 = None;
let mut set3 = None;
let mut set2 = [0; 2];
for card in cards {
suits[card.suit as usize] = true;
ranks[card.rank as usize] += 1;
match ranks[card.rank as usize] {
0 => unreachable!(),
1 => {}
2 => {
if set2[0] > 0 {
debug_assert_eq!(set2[1], 0);
set2[1] = card.rank;
} else {
set2[0] = card.rank;
}
}
3 => {
debug_assert_eq!(set3, None);
set3 = Some(card.rank);
if set2[0] == card.rank {
set2[0] = set2[1];
set2[1] = 0;
} else {
debug_assert_eq!(set2[1], card.rank);
set2[1] = 0;
}
}
4 => {
debug_assert_eq!(set4, None);
set4 = Some(card.rank);
}
5 => {
eprintln!("5 of a kind?")
}
_ => unreachable!(),
}
}
if let Some(rank) = set4 {
PokerHand::FourOfAKind(rank)
} else if let Some(rank) = set3 {
if set2[0] > 0 {
PokerHand::FullHouse(rank, set2[0])
} else {
PokerHand::ThreeOfAKind(rank)
}
} else if set2[1] > 0 {
cards.sort_unstable_by_key(|c| std::cmp::Reverse(*c));
PokerHand::TwoPair(set2)
} else if set2[0] > 0 {
PokerHand::Pair(set2[0])
} else {
cards.sort_unstable_by_key(|c| std::cmp::Reverse(*c));
let is_flush = suits.into_iter().filter(|y| *y).count() == 1;
let is_straight = cards.windows(2)
.all(|p|
p[0].rank == p[1].rank + 1
|| p[0].rank == 14 && p[1].rank == 5);
// Handle Ace being high or low.
let straight_rank = if ranks[2] > 0 { 5 } else { cards[0].rank };
match (is_flush, is_straight) {
(true, true) => PokerHand::StraightFlush(straight_rank),
(true, false) => PokerHand::Flush(cards.map(|c| c.rank)),
(false, true) => PokerHand::Straight(straight_rank),
(false, false) => PokerHand::High(cards.map(|c| c.rank)),
}
}
}
Editor is loading...
Leave a Comment