1use rand::prelude::*;
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[cfg(feature = "parallel")]
10pub mod parallel;
11
12const PRIMES: [u32; 13] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41];
14
15#[derive(Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
17pub struct Card(u32);
18
19impl Card {
21 pub fn new(rank: Rank, suit: Suit) -> Card {
23 let (rank, suit) = (rank as u32, suit as u32);
36 Self(PRIMES[rank as usize] | (rank << 8) | (suit << 12) | (1 << (rank + 16)))
37 }
38
39 pub fn id(&self) -> u32 {
41 self.0
42 }
43
44 pub fn suit(&self) -> Suit {
46 let suit_bits = self.suit_bits();
47 match suit_bits {
48 0x8 => Suit::Clubs,
49 0x4 => Suit::Diamonds,
50 0x2 => Suit::Hearts,
51 0x1 => Suit::Spades,
52 _ => panic!("Invalid suit value 0x{:x}", self.0),
53 }
54 }
55
56 pub fn rank(&self) -> Rank {
58 let rank_bits = self.rank_bits();
59 match rank_bits {
60 0 => Rank::Deuce,
61 1 => Rank::Trey,
62 2 => Rank::Four,
63 3 => Rank::Five,
64 4 => Rank::Six,
65 5 => Rank::Seven,
66 6 => Rank::Eight,
67 7 => Rank::Nine,
68 8 => Rank::Ten,
69 9 => Rank::Jack,
70 10 => Rank::Queen,
71 11 => Rank::King,
72 12 => Rank::Ace,
73 _ => panic!("Invalid rank 0x{:x}", self.0),
74 }
75 }
76
77 #[inline]
79 pub fn rank_bits(&self) -> u8 {
80 ((self.0 >> 8) & 0xf) as u8
81 }
82
83 #[inline]
85 pub fn suit_bits(&self) -> u8 {
86 ((self.0 >> 12) & 0xf) as u8
87 }
88}
89
90impl Default for Card {
91 fn default() -> Self {
92 Card::new(Rank::Ace, Suit::Diamonds)
93 }
94}
95
96impl fmt::Display for Card {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 write!(f, "{}{}", self.rank(), self.suit())
99 }
100}
101
102impl fmt::Debug for Card {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(f, "Card({}{})", self.rank(), self.suit())
105 }
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
110pub enum Rank {
111 Deuce = 0,
113 Trey,
115 Four,
117 Five,
119 Six,
121 Seven,
123 Eight,
125 Nine,
127 Ten,
129 Jack,
131 Queen,
133 King,
135 Ace,
137}
138
139impl Rank {
140 pub fn ranks() -> impl DoubleEndedIterator<Item = Rank> {
142 use Rank::*;
143 [
144 Deuce, Trey, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace,
145 ]
146 .into_iter()
147 }
148}
149
150impl fmt::Display for Rank {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 let rank = match self {
153 Rank::Deuce => '2',
154 Rank::Trey => '3',
155 Rank::Four => '4',
156 Rank::Five => '5',
157 Rank::Six => '6',
158 Rank::Seven => '7',
159 Rank::Eight => '8',
160 Rank::Nine => '9',
161 Rank::Ten => 'T',
162 Rank::Jack => 'J',
163 Rank::Queen => 'Q',
164 Rank::King => 'K',
165 Rank::Ace => 'A',
166 };
167
168 write!(f, "{rank}")
169 }
170}
171
172#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
174pub enum Suit {
175 Clubs = 8,
177 Diamonds = 4,
179 Hearts = 2,
181 Spades = 1,
183}
184
185impl fmt::Display for Suit {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 let suit = match self {
188 Suit::Clubs => 'C',
189 Suit::Diamonds => 'D',
190 Suit::Hearts => 'H',
191 Suit::Spades => 'S',
192 };
193
194 write!(f, "{suit}")
195 }
196}
197
198impl Suit {
199 pub fn suits() -> impl DoubleEndedIterator<Item = Suit> {
201 [Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades].into_iter()
202 }
203}
204
205#[derive(Debug)]
207pub struct Deck {
208 cards: Vec<Card>,
209}
210
211impl Deck {
212 pub const SIZE: usize = 52;
214
215 pub fn shuffled<R: Rng>(rng: &mut R) -> Self {
217 let mut deck = Self::default();
218 deck.cards.shuffle(rng);
219 deck
220 }
221
222 pub fn deal(&mut self) -> Card {
224 self.cards.pop().unwrap()
225 }
226
227 pub fn is_empty(&self) -> bool {
229 self.cards.is_empty()
230 }
231
232 pub fn count(&self) -> usize {
234 self.cards.len()
235 }
236
237 pub fn remove(&mut self, card: Card) {
239 self.cards.retain(|c| c != &card);
240 }
241
242 pub fn sample<F>(&self, n: usize, k: usize, mut f: F)
246 where
247 F: FnMut(&[Card]),
248 {
249 assert!(k > 0 && k < self.cards.len());
250
251 let mut h = vec![Card::new(Rank::Ace, Suit::Hearts); k];
252 let mut rng = SmallRng::from_os_rng();
253
254 for _ in 0..n {
255 for (pos, c) in self.cards.choose_multiple(&mut rng, k).enumerate() {
256 h[pos] = *c;
257 }
258
259 f(&h);
260 }
261 }
262
263 pub fn for_each<F>(&self, k: usize, mut f: F)
267 where
268 F: FnMut(&[Card]),
269 {
270 assert!(2 <= k && k <= 7, "2 <= k <= 7");
271
272 if k > self.cards.len() {
273 return;
274 }
275
276 let n = self.cards.len();
277 let mut h = vec![Card::new(Rank::Ace, Suit::Hearts); 7];
278
279 for c1 in 0..n {
280 h[0] = self.cards[c1];
281
282 for c2 in (c1 + 1)..n {
283 h[1] = self.cards[c2];
284
285 if k == 2 {
286 f(&h[0..k]);
287 continue;
288 }
289
290 for c3 in (c2 + 1)..n {
291 h[2] = self.cards[c3];
292
293 if k == 3 {
294 f(&h[0..k]);
295 continue;
296 }
297
298 for c4 in (c3 + 1)..n {
299 h[3] = self.cards[c4];
300
301 if k == 4 {
302 f(&h[0..k]);
303 continue;
304 }
305
306 for c5 in (c4 + 1)..n {
307 h[4] = self.cards[c5];
308
309 if k == 5 {
310 f(&h[0..k]);
311 continue;
312 }
313
314 for c6 in (c5 + 1)..n {
315 h[5] = self.cards[c6];
316
317 if k == 6 {
318 f(&h[0..k]);
319 continue;
320 }
321
322 for c7 in (c6 + 1)..n {
323 h[6] = self.cards[c7];
324 f(&h[0..k]);
325 }
326 }
327 }
328 }
329 }
330 }
331 }
332 }
333}
334
335impl Default for Deck {
336 fn default() -> Self {
337 let cards = Suit::suits()
338 .flat_map(|s| Rank::ranks().map(move |r| Card::new(r, s)))
339 .collect::<Vec<_>>();
340 Self { cards }
341 }
342}
343
344impl IntoIterator for Deck {
345 type Item = Card;
346 type IntoIter = std::vec::IntoIter<Card>;
347
348 fn into_iter(self) -> Self::IntoIter {
349 self.cards.into_iter()
350 }
351}
352
353#[cfg(test)]
354mod tests {
355 use super::*;
356 use ahash::HashSet;
357
358 #[test]
359 fn card_encoding() {
360 let mut cards = HashSet::default();
361 let mut deck = Deck::shuffled(&mut rand::rng());
362
363 while !deck.is_empty() {
364 let card = deck.deal();
365 assert_eq!(card.id() & 0xFF, PRIMES[card.rank() as usize]);
366 assert_eq!((card.id() >> 8) & 0xF, card.rank() as u32);
367 assert_eq!((card.id() >> 12) & 0xF, card.suit() as u32);
368 assert_eq!(card.id() >> 16, 1 << (card.rank() as usize));
369 cards.insert(card.id());
370 }
371
372 assert_eq!(cards.len(), Deck::SIZE);
374
375 let kd = Card::new(Rank::King, Suit::Diamonds);
377 assert_eq!(kd.id(), 0x08004b25);
378
379 let fs = Card::new(Rank::Five, Suit::Spades);
380 assert_eq!(fs.id(), 0x00081307);
381
382 let jc = Card::new(Rank::Jack, Suit::Clubs);
383 assert_eq!(jc.id(), 0x0200891d);
384 }
385
386 #[test]
387 fn card_to_string() {
388 let c = Card::new(Rank::King, Suit::Diamonds);
389 assert_eq!(c.to_string(), "KD");
390
391 let c = Card::new(Rank::Five, Suit::Spades);
392 assert_eq!(c.to_string(), "5S");
393
394 let c = Card::new(Rank::Jack, Suit::Clubs);
395 assert_eq!(c.to_string(), "JC");
396
397 let c = Card::new(Rank::Ten, Suit::Hearts);
398 assert_eq!(c.to_string(), "TH");
399
400 let c = Card::new(Rank::Ace, Suit::Hearts);
401 assert_eq!(c.to_string(), "AH");
402 }
403
404 #[test]
405 fn deck_for_each() {
406 let deck = Deck::default();
407 assert_eq!(deck.count(), Deck::SIZE);
408
409 let mut hands = HashSet::default();
410 deck.for_each(5, |cards| {
411 assert_eq!(cards.len(), 5);
412 hands.insert(cards.to_owned());
413 });
414 assert_eq!(hands.len(), 2_598_960);
415
416 hands.clear();
417 deck.for_each(2, |cards| {
418 assert_eq!(cards.len(), 2);
419 hands.insert(cards.to_owned());
420 });
421 assert_eq!(hands.len(), 1_326);
422
423 hands.clear();
424 deck.for_each(3, |cards| {
425 assert_eq!(cards.len(), 3);
426 hands.insert(cards.to_owned());
427 });
428 assert_eq!(hands.len(), 22_100);
429 }
430
431 #[test]
432 fn deck_for_each_7cards() {
433 let deck = Deck::default();
434
435 let mut count = 0;
436 deck.for_each(7, |cards| {
437 assert_eq!(cards.len(), 7);
438 count += 1;
439 });
440 assert_eq!(count, 133_784_560);
441 }
442
443 #[test]
444 fn deck_for_each_remove() {
445 let mut deck = Deck::default();
446 deck.remove(Card::new(Rank::Ace, Suit::Diamonds));
447 deck.remove(Card::new(Rank::King, Suit::Diamonds));
448
449 let mut count = 0;
450 deck.for_each(7, |cards| {
451 assert_eq!(cards.len(), 7);
452 count += 1;
453 });
454 assert_eq!(count, 99_884_400);
455 }
456
457 #[test]
458 fn sample() {
459 let mut counter = 0;
460 Deck::default().sample(10, 1, |hand| {
461 assert_eq!(hand.len(), 1);
462 counter += 1;
463 });
464 assert_eq!(counter, 10);
465
466 let mut counter = 0;
467 Deck::default().sample(10, 7, |hand| {
468 assert_eq!(hand.len(), 7);
469 counter += 1;
470 });
471 assert_eq!(counter, 10);
472 }
473}