Frustration is a solitaire card game which is played by calling out the sequence:

“Ace”, “Two”, “Three”, ... , "Nine", "Ten", “Jack”, “Queen”, “King”, “Ace”, “Two”, etc.

With each call, you simultaneously flip over a card from a shuffled deck of 52 cards. You win the game if you get through the entire deck without ever calling out the rank of the card being flipped over.


Given a string or list of characters representing an ordered deck of cards, return "Truthy" if the deck is a winning Frustration configuration, and return "Falsy" otherwise


Input will be a single string (or a list of characters, or a list of codepoints) consisting solely of the following 13 characters (you may choose to take the letters as uppercase or lowercase):

A 2 3 4 5 6 7 8 9 T J Q K

Each character will be repeated 4 times in the input. An example of a valid input is:


You may assume that the input is always valid (ie. it will contain exactly 52 characters and the 13 characters mentioned above will be repeated exactly 4 times each)


Output one of two distinct "Truthy" and "Falsy" values. The values you choose must be consistent (ie. different "Truthy" inputs must produce the same "Truthy" output and different "Falsy" inputs must produce the same "Falsy" output)


The input KA23456789TJQKA23456789TJQKA23456789TJQKA23456789TJQ would be a winning Frustration configuration (hence a "Truthy" input) because none of the cards in the sequence match the name called out when flipping that card over.

The input 2K3A456789TJQKA23456789TJQKA23456789TJQKA23456789TJQ would not be a winning Frustration configuration (hence a "Falsy" input) because the 3rd card flipped over matches the name called out when flipping it (3).

Test Cases (one per line)






This is . Shortest answer in bytes wins

  • 1
    \$\begingroup\$ @KevinCruijssen Yes, that's fine \$\endgroup\$ Apr 28, 2020 at 14:28

20 Answers 20


Python 2, 45 42 bytes

-5 bytes thanks to @ovs

lambda s:all(map(cmp,s,'A23456789TJQK'*4))

Try it online!

  • 3
    \$\begingroup\$ Can you use all instead of 0not in ? \$\endgroup\$
    – ovs
    Apr 24, 2020 at 22:21
  • \$\begingroup\$ Thanks for the tip! I've never thought of using all for integers. \$\endgroup\$ Apr 24, 2020 at 22:27

Perl 5 -p, 29 bytes


Try it online!

Perl allows XOR on strings, how awesome is that?!

  • 1
    \$\begingroup\$ -p means that the language is perl 5 -p. The add bytes to your score is an old rule that has been superseded. \$\endgroup\$
    – S.S. Anne
    Apr 25, 2020 at 20:20
  • \$\begingroup\$ thanks for that, for anyone else wanting a reference to the rule, i found it here: codegolf.meta.stackexchange.com/questions/14337/… \$\endgroup\$
    – Jarmex
    Apr 25, 2020 at 20:56

Jelly, 14 bytes


A monadic Link accepting a list of characters which yields 0 or 1.

Try it online!


QṢ“ṡ=2E’œ?ṁn⁸Ạ - Link: list of characters, D
Q              - de-duplicate D
 Ṣ             - sort
  “ṡ=2E’       - base 250 integer = 3,832,012,820
        œ?     - nth permutation
          ṁ    - mould like (D)
           n   - not equal? (vectorises):
            ⁸  -   chain's left argument, D
             Ạ - all?
  • \$\begingroup\$ Does nth permutation require sorting? \$\endgroup\$ Apr 25, 2020 at 5:57
  • \$\begingroup\$ We need to sort before applying it as the right argument defines the 1st permutation. "Permutation at index x of the items in y (where y defines the sort order of those items)." \$\endgroup\$ Apr 25, 2020 at 15:22

Bash + Core utilities, 48 bytes

egrep "`echo \([^A ][^{{2..9},T,J,Q,K} ]\){4}`"

Try the test cases online!

Input is on stdin.

Output is the exit code: 0 for truthy, 1 for falsy.


Retina 0.8.2, 57 bytes


Try it online! Link includes test cases. Explanation: Simply matches a string of 52 bytes that doesn't match the specified character at each given position.


Haskell, 37 bytes


Try it online!


05AB1E, 19 bytes

-2 bytes thanks to EdgyNerd,

-1 byte thanks to Grimmy.


Try it online!

  • \$\begingroup\$ And I've asked OP if lowercase input is allowed, in which case 'A8L>"TJQK"JJ could be 8L>J.•§®т•«Á (if not, an additional u is required and it's the same byte-count for this first part). Also @petStorm, you might want to mention you inverted the truthy/falsey in your output.. \$\endgroup\$ Apr 28, 2020 at 6:53
  • \$\begingroup\$ OP confirmed that taking the input as lowercase is allowed, so here is 17: 8L>J.•§®т•«ÁÞø€Ëà (still outputs 0 for truthy; 1 for falsey). \$\endgroup\$ Apr 28, 2020 at 14:39

JavaScript (ES6), 48 bytes

With the input being a string:

With the input as an array of char it's down to 43 bytes:

var f=




Java (JDK), 63 bytes


Try it online!


Wolfram Language (Mathematica), 58 bytes


Try it online! Pure function. Takes a list of characters as input and returns True or False as output. Note that this function checks for losing configurations (since Equal and Or are shorter than Unequal and And), so False is the truthy value and True is the falsy value.


APL (Dyalog Unicode), 44 bytesSBCS

{A T J Q K←10+¯9 0 1 2 3⋄~∨/(13|⍳52)=13|⍎¨⍵}

Try it online!


Charcoal, 19 bytes


Try it online! Link is to verbose version of code. Outputs a Charcoal boolean; - for truthy, nothing for falsy. Explanation:

 θ                  Input string
⬤                   All characters satisfy
    ι               Current character
  ¬⁼                Not equal to
        …²χ         Digits from 2 to 9
       ⪫   ω        Joined together
      ⁺     TJQKA   Suffixed with picture cards
     §              Indexed by
                 ⊖κ Current index incremented

Perl 5, 36 bytes

sub f{('A23456789TJQK'x4^pop)!~/\0/}

Try it online!

'A23456789TJQK' x 4 results in the 52 byte string of A23456789TJQK repeated four times.

This string is bitwise XOR-ed (operator ^) by the equal length input string from pop.

Any equal byte (char) at the same positions in the two strings results in a null-byte from xor.

And !~ (not regex-match) returns true if no null-byte \0 exists. Otherwise false.


C (gcc), 64 bytes


Outputs zero for truthy and non-zero for falsy.

Try it online!


J, 26 bytes

1 e.(52$'A23456789TJQK')&=

Try it online!

0 is truthy, 1 is falsy.

Straightforward as possible, posted mostly as a straw man because I thought it was interesting that there didn't seem to be a trick to compress 'A23456789TJQK' that was shorter than the literal.


K (oK), 24 bytes


Try it online!

  • (52#"A23456789TJQK") build the frustration sequence
  • (...)= compare it to the input
  • ~|/ do none (i.e. not any) match?

Pyth, 24 20 bytes


Try it online!

  • X1"ATJQK"jkr2T Construct the string "A23456789TJQK". Inserting the range 2-9 at position 1 of "ATJQK" is one byte shorter than using the full string literal

  • * ... 4 Duplicate that string 4 times

  • V Vectorize the above string and the input string as inputs to the following function:

    • q (arg1) == (arg2)
  • !s Return true if the result sums to 0 (ie. none of the cards from the input match the above string)


GolfScript, 29 bytes


Try it online!

"A23456789TJQK"4*               # Push this string repeted 4 times
                 ]zip           # Zip the input and the previous string
                     {    },    # Find all elements that pass this test
                      1/        # Divide in groups of 1      "XY" -> ["X" "Y"]
                        ~=      # Are they equal?
                            !   # Is it an empty array?

Outputs 1 for truthy and 0 for falsy.


Japt -e, 16 bytes

kVg"tjqk"i9õ ¬ha

Try it


x86 machine code, 33 32 bytes

Replace xx xx xx xx with the address of .Llut.

Machine code:

00000034: bb xx xx xx xx 6a 34 59 89 c8 d4 0d d7 ae 74 02  .....j4Y......t.
00000044: e2 f6 c3 41 4b 51 4a 54 39 38 37 36 35 34 33 32  ...AKQJT98765432

Commented assembly:

        .intel_syntax noprefix
        .section .text
        .globl frustration
        // Input: EDI: 52 byte string to test
        // Clobbers: EAX, ECX, EBX, EDI
        // Output: ECX: Zero for true, non-zero for false
        // Load the lookup table into EBX.
        mov     ebx, offset .Llut
        // Set ECX to 52 for our loop iterator
        push    52
        pop     ecx
        // Copy ECX to EAX
        mov     eax, ecx
        // Convert to the LUT index. Read the .Llut comment before
        // questioning my math. ;)
        // AL = AL % 13, AH = AH / 13
        aam     13
        // Load the corresponding card rank into AL.
        // AL = EBX[AL]
        // Compare to the byte in EDI, increment EDI
        scas    al, byte ptr [edi]
        // If it was equal, return. ECX will be nonzero.
        // Note that loopne wouldn't work: it decrements first, so it
        // won't work for the last card. :(
        je      .Lfalse
        // Loop for 52 iterations
        loop    .Lloop
        // At this point, ECX is zero from the loop, our "truthy" value
        // We store our LUT in a slightly unsual order.
        // This is because we are looping from 52->0, and using
        // the index mod 13 to get the index. However, we read
        // forwards, and we decrement AFTER the modulo.
        // This means we need to reverse, then rotate one byte.
        //  0  52  0
        //  1  51 12
        //  2  50 11
        // ....
        // 12  40  1
        .ascii "AKQJT98765432"

Try it online!

The function takes the string pointer in edi and returns, in ecx, either zero for a win, or non-zero for a loss.

Doesn't follow standard calling convention.

I finally found a good use for both aam and xlatb, I feel accomplished.

See the comments for details.

This could use 2 fewer bytes on 16-bit, but that is solely because the LUT address is 2 bytes smaller. No fancy 16-bit tricks, so I'll leave it at x86 because it is easily testable on TIO.

I'd love to trim down this LUT a bit, but I'm not currently sure how. The LUT is 13 bytes plus a 5 byte mov, making more than half of the code.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.