classifier: permit loop-around straights
Our classifier now permits straights like (A(S), 2(D), 3(C), 4(S), 5(H)).
This commit is contained in:
@@ -29,6 +29,12 @@ pub enum Card {
|
||||
PlayingCard { deck: i64, rank: Rank, suit: Suit },
|
||||
}
|
||||
|
||||
impl Rank {
|
||||
pub fn ordinary_order(&self) -> i32 {
|
||||
((*self as i32) + 2) % 13
|
||||
}
|
||||
}
|
||||
|
||||
impl Card {
|
||||
pub fn is_joker(&self) -> bool {
|
||||
matches!(self, Self::Joker(_))
|
||||
@@ -56,7 +62,7 @@ pub fn make_decks(number_of_decks: usize) -> Vec<Card> {
|
||||
.collect::<Vec<Card>>()
|
||||
}
|
||||
|
||||
mod impls {
|
||||
mod traits {
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
@@ -168,22 +168,44 @@ fn all_same_rank(cards: &[Card]) -> bool {
|
||||
}
|
||||
|
||||
fn is_straight(num_jokers: i32, cards: &[Card]) -> bool {
|
||||
// TODO: allow straights where Ace or 2 are the first members (loop-around
|
||||
// straights).
|
||||
let mut num_jokers = num_jokers;
|
||||
for i in 0..(cards.len() - 1) {
|
||||
let r1 = cards[i].rank().unwrap() as i32;
|
||||
let r2 = cards[i + 1].rank().unwrap() as i32;
|
||||
let diff = r2 - r1;
|
||||
if diff == 0 || diff - 1 > num_jokers {
|
||||
/** Given a slice `nums` (presumed ascending ordered) and the amount of allowed
|
||||
* `gaps`, figure out if the nums are actually a consecutive sequence.
|
||||
*/
|
||||
fn strictly_consecutive_numbers<I>(mut nums: I, mut gaps: i32) -> bool
|
||||
where
|
||||
I: Iterator<Item = i32>,
|
||||
{
|
||||
let mut prev = match nums.next() {
|
||||
Some(n) => n,
|
||||
None => unreachable!("Iterator should not be empty"),
|
||||
};
|
||||
for m in nums {
|
||||
let diff = m - prev;
|
||||
if diff == 0 || diff - 1 > gaps {
|
||||
return false;
|
||||
}
|
||||
num_jokers -= diff - 1;
|
||||
gaps -= diff - 1;
|
||||
if gaps < 0 {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
prev = m;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
mod impls {
|
||||
let ranks = cards.iter().map(|x| x.rank().unwrap() as i32);
|
||||
|
||||
if !strictly_consecutive_numbers(ranks, num_jokers) {
|
||||
// If we don't have a strictly consecutive sequence, try using an
|
||||
// ordinary order where Ace is the lowest rank and king is the highest.
|
||||
let ranks = cards.iter().map(|x| x.rank().unwrap().ordinary_order());
|
||||
strictly_consecutive_numbers(ranks, num_jokers)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
mod traits {
|
||||
use super::*;
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user