use itertools::Itertools;
use variter::VarIter;
use crate::{
card::{rank::Rank, Card},
constants::{INT_RANKS, PRIMES},
evaluate::lookup_table,
};
#[derive(Clone)]
struct BitSequence {
bits: i16,
t: i16,
next_bits: i16,
}
impl BitSequence {
const fn new(bits: i16) -> Self {
Self {
bits,
t: 0,
next_bits: 0,
}
}
}
impl Iterator for BitSequence {
type Item = i16;
fn next(&mut self) -> Option<Self::Item> {
self.t = self.bits | self.bits.wrapping_sub(1);
self.next_bits = self.t.wrapping_add(1);
self.next_bits |= ((!self.t & -!self.t) - 1) >> self.bits.trailing_zeros().wrapping_add(1);
self.bits = self.next_bits;
Some(self.next_bits)
}
}
pub fn bit_sequence_generator(bits: i16) -> impl Iterator<Item = i16> { BitSequence::new(bits) }
pub fn combinations_generator<I>(iterable: I, r: usize) -> impl Iterator<Item = Vec<I::Item>>
where
I: IntoIterator,
I::Item: Clone,
{
iterable.into_iter().combinations(r)
}
pub fn prime_product_from_rank_bits(rank_bits: i16) -> i32 {
let mut product = 1;
for i in INT_RANKS {
if rank_bits & (1 << i) != 0 {
product *= PRIMES[i as usize]
}
}
product
}
pub fn prime_product_from_hand(hand: &[Card]) -> i32 {
let mut product = 1;
for &card in hand {
product *= card.unique_integer() & 0xFF
}
product
}
pub fn high_rank_from_rank_bits(rank_bits: i16) -> Rank {
if rank_bits == lookup_table::constants::STRAIGHTS[9] {
return Rank::Five;
}
for i in INT_RANKS.rev() {
if rank_bits & (1 << i) != 0 {
return Rank::ALL_VARIANTS[i as usize];
}
}
unreachable!();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn combinations_generator_works() {
let combos = combinations_generator(vec!['c', 'a', 't'], 2).collect::<Vec<_>>();
let expected_combos: [[char; 2]; 3] = [['c', 'a'], ['c', 't'], ['a', 't']];
assert_eq!(combos.len(), expected_combos.len());
for &combo in &expected_combos {
assert!(combos.contains(&combo.into()));
}
}
#[test]
fn bit_sequence_generator_works() {
let some_number = 0b10011;
let mut xs = bit_sequence_generator(some_number);
let mut next_check = move |bin: i16| {
assert_eq!(xs.next().unwrap(), bin);
};
next_check(0b00010101);
next_check(0b00010110);
next_check(0b00011001);
next_check(0b00011010);
next_check(0b00011100);
next_check(0b00100011);
}
}