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 },
|
PlayingCard { deck: i64, rank: Rank, suit: Suit },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rank {
|
||||||
|
pub fn ordinary_order(&self) -> i32 {
|
||||||
|
((*self as i32) + 2) % 13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Card {
|
impl Card {
|
||||||
pub fn is_joker(&self) -> bool {
|
pub fn is_joker(&self) -> bool {
|
||||||
matches!(self, Self::Joker(_))
|
matches!(self, Self::Joker(_))
|
||||||
@@ -56,7 +62,7 @@ pub fn make_decks(number_of_decks: usize) -> Vec<Card> {
|
|||||||
.collect::<Vec<Card>>()
|
.collect::<Vec<Card>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
mod impls {
|
mod traits {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::{Display, Formatter};
|
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 {
|
fn is_straight(num_jokers: i32, cards: &[Card]) -> bool {
|
||||||
// TODO: allow straights where Ace or 2 are the first members (loop-around
|
/** Given a slice `nums` (presumed ascending ordered) and the amount of allowed
|
||||||
// straights).
|
* `gaps`, figure out if the nums are actually a consecutive sequence.
|
||||||
let mut num_jokers = num_jokers;
|
*/
|
||||||
for i in 0..(cards.len() - 1) {
|
fn strictly_consecutive_numbers<I>(mut nums: I, mut gaps: i32) -> bool
|
||||||
let r1 = cards[i].rank().unwrap() as i32;
|
where
|
||||||
let r2 = cards[i + 1].rank().unwrap() as i32;
|
I: Iterator<Item = i32>,
|
||||||
let diff = r2 - r1;
|
{
|
||||||
if diff == 0 || diff - 1 > num_jokers {
|
let mut prev = match nums.next() {
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
gaps -= diff - 1;
|
||||||
|
if gaps < 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
prev = m;
|
||||||
}
|
}
|
||||||
num_jokers -= diff - 1;
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod impls {
|
mod traits {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::fmt::{Display, Formatter, Result};
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user