Teaser 3297: 6oker
From The Sunday Times, 30th November 2025 [link] [link]
6oker is a 6-card version of poker. Like 5-card poker the rank of a hand is based on the number of distinct variants of that type possible from a 52-card pack. Fewer variants gives a higher (winning) rank. For example, a running flush ({A, 2, 3, 4, 5} to {10, J, Q, K, A} in one suit) has 40 variants, beating four-of-a-kind (e.g., four aces with another card) which has 624 variants.
Playing 6oker, Al and Di held hands of different rank. Each comprised only two card values and no aces, jacks, queens or kings (e.g., four 3s and two 6s). These four values had no common prime factors.
Ignoring suits, if you were told just Al’s hand you couldn’t be sure of Di’s, but if you were told just Di’s you could be sure of Al’s.
Who won? Ignoring suits, give Al’s hand.
[teaser3297]









Jim Randell 7:41 am on 30 November 2025 Permalink |
With 6 cards of two different values you must be holding either 2 of one value and 4 of the other (936 variants), or holding 3 of each value (1248 variants). (I wrote some code to check all possible 6-card hands to ensure I got these numbers correct).
So the first type of hand is a higher rank than the second. And one type is Al’s and the other is Di’s (and whoever has the higher rank wins).
This Python program generates the possible values in each hand, and uses the [[
filter_unique()]] function from the enigma.py library to determine possible distributions of cards in each hand.It runs in 71ms. (Internal runtime is 788µs).
from enigma import ( irange, subsets, is_coprime, diff, filter_unique, item, intersect, ulambda, sprintf, printf ) # generate possible values in the hands def generate(): # find 4 card values with that are pairwise coprime for vs in subsets(irange(2, 10), size=4): if not is_coprime(*vs): continue # choose 2 values for A for A in subsets(vs, size=2): D = diff(vs, A) yield (A, D) # possible distribution of values hs = list() for ((a1, a2), (d1, d2)) in generate(): # record possible hands (value, quantity) hs.extend([ (((a1, 3), (a2, 3)), ((d1, 2), (d2, 4))), (((a1, 3), (a2, 3)), ((d1, 4), (d2, 2))), (((a1, 2), (a2, 4)), ((d1, 3), (d2, 3))), (((a1, 4), (a2, 2)), ((d1, 3), (d2, 3))), ]) # format a hand fmt = ulambda('((v1, q1), (v2, q2)): sprintf("{q1}x {v1}s + {q2}x {v2}s")') # if we were just told A we couldn't deduce D hs1 = filter_unique(hs, f=item(0), g=item(1)).non_unique # if we were just told D we could deduce A hs2 = filter_unique(hs, f=item(1), g=item(0)).unique # the answer must be in the intersection for (A, D) in intersect([hs1, hs2]): win = ("A" if D[0][1] == 3 else "D") # whoever has "3 and 3" is the loser # output scenario printf("A=({A}) D=({D}); win = {win}", A=fmt(A), D=fmt(D))Solution: Di won. Al was holding three 5s and three 7s.
Di is holding two cards of one value, and four cards of another value. The values are one of:
LikeLike
Frits 7:55 pm on 2 December 2025 Permalink |
@Jim,
Is there a special reason why you determine the intersection?
I assume list “hs2” can be built directly from list “hs1”.
LikeLike
Jim Randell 8:43 am on 3 December 2025 Permalink |
@Frits:
hs1is the set of possible hands (ignoring suits) where if we knew A’s hand we could not deduce D’s hand.hs2is the set of possible hands where if we knew D’s hand we could deduce A’s hand. For a valid solution to the puzzle the hands must satisfy both these conditions, so we look at the intersection of these two sets (i.e. the elements that are in both sets).LikeLike
Pete Good 7:55 pm on 30 November 2025 Permalink |
Jim, I agree that 3 + 3 has a higher rank than 4 + 2 so the player with 3 + 3 wins, but the comment in your program says that whoever has 3 and 3 is the loser?!
LikeLike
Jim Randell 9:48 pm on 30 November 2025 Permalink |
@Pete: I calculated that “4 and 2” has fewer variants than “3 and 3”, so “4 and 2” is the better hand.
LikeLike
Pete Good 11:13 am on 1 December 2025 Permalink |
Thanks Jim. I misunderstood the ranking process described in the teaser.
LikeLike