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:
2026-04-01 04:04:52 +01:00
committed by oreodave
parent dd0011d1f2
commit 14d66cf171
2 changed files with 41 additions and 13 deletions

View File

@@ -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};

View File

@@ -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() {
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; 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 super::*;
use std::fmt::{Display, Formatter, Result}; use std::fmt::{Display, Formatter, Result};