I found this YouTube video with a table on it showing some card suits with ampersands. You might not understand what it is about, but I still want to make a challenge about it.

The input is two suits, being one of the following:


You can do anything for any other input.

Then the output is their 'game sum':

  1. If both suits are red (heart/diamond), then:
    • Up to one heart promotes to a spade
    • Up to one diamond demotes to a club
  2. Output in order of priority (spade > heart > diamond > club).

Leading and trailing whitespace is allowed.

Example input:


Example output:

spade and heart

Use any language. This is code-golf, so shortest code in bytes wins.

  • 1
    \$\begingroup\$ Is the output club and spade an acceptable alternative for spade and club, or does the order matter? \$\endgroup\$
    – Arnauld
    Jan 9 at 22:04
  • \$\begingroup\$ @Arnauld The order matters. "club and spade" is not an acceptable alternative for "spade and club". \$\endgroup\$ Jan 9 at 22:23
  • 7
    \$\begingroup\$ Unless you provide some motivation, this looks like an arbitrary and somewhat boring task. If there is a rule or pattern that governs the input-output relationship, finding it out should not be a part of the challenge \$\endgroup\$
    – Luis Mendo
    Jan 9 at 22:50
  • 1
    \$\begingroup\$ The video this question is based does not even provide any justification for this pattern, only showing this table briefly from what looks like a book. \$\endgroup\$
    – Tbw
    Jan 10 at 3:51
  • 5
    \$\begingroup\$ The order pf precedence (sorting order) Spade Heart Diamond Club is from the game Bridge (and is coincidentally reverse alphabetical order.) Cards stay the same unless both are red, in which case the first available heart is promoted to spade and the last available diamond is demoted to club. I've watched the video and it gives no clue why this should be the case. \$\endgroup\$ Jan 10 at 10:20

7 Answers 7


Retina 0.8.2, 58 bytes

spade $&
$& club
( .+)?¶(.+ )?

Try it online! Takes input on separate lines but link is to test suite that splits on + for convenience. Explanation:


Sort in reverse order.

spade $&

Prefix spade if heart is followed by either heart or diamond.

$& club

Suffix club if either heart or diamond are followed by diamond.

( .+)?¶(.+ )?

Keep only the first and last words and join them with and.


05AB1E, 33 bytes

„‰áš¸#©¢O<i®“spade†Ú“#.;}{R„ €ƒÀý

Input as a pair of strings.

Try it online or verify all test cases.


„‰áš¸                 # Push dictionary string "heart diamond"
     #                # Split it on spaces: ["heart","diamond"]
      ©               # Store this pair in variable `®` (without popping)
       ¢              # Count how many times each occurs in the (implicit) input-pair
        O             # Sum those counts together
         <i           # If it's 2:
                      # (this is only truthy for the following four pairs: dd,dh,hd,hh)
           ®          #  Push ["heart","diamond"] again from variable `®`
           “spade†Ú“  #  Push dictionary string "spade club"
                    # #  Split it on spaces as well: ["spade","club"]
           .;         #  Replace the first "heart" with "spade" and first "diamond"
                      #  with "club" in the (implicit) input-pair
          }           # Close the if-statement
                      # (the implicit else uses the implicit input-pair)
           {R         # Sort the pair in descending order (sort + reverse)
             „ €ƒ     # Push dictionary string "  and"
                 À    # Rotate it once to the left to " and "
                  ý   # Join the pair with " and " as delimiter
                      # (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why „‰áš¸ is "heart diamond"; “spade†Ú“ is "spade club"; and „ €ƒ is " and".


JavaScript (ES6), 80 bytes

-6 thanks to @tsh

Inspired by Neil's method.

Expects ([a, b]).

c=>(/[dt],h/.test([b,a]=c.sort())?"spade":a)+" and "+(/d,[dh]/.test(c)?"club":b)

Try it online!


c =>           // c[] = input array
(              //
  /[dt],h/     // if a is "heart" and b is
  .test(       // either "heart" or "diamond",
    [b, a] =   // where a and b are sorted such
      c.sort() // that a > b:
  ) ?          //
    "spade"    //   use "spade" as the left output
  :            // else:
    a          //   use a
) +            //
" and " +      // append " and "
(              //
  /d,[dh]/     // if b is "diamond" and a is
  .test(c) ?   // either "diamond" or "heart":
    "club"     //   use "club" as the right output
  :            // else:
    b          //   use b
)              //
  • 1
    \$\begingroup\$ 80 bytes if input as an array: c=>(/[dt],h/.test([b,a]=c.sort())?"spade":a)+" and "+(/d,[dh]/.test(c)?"club":b) or c=>(/[dt],h/.test(c.sort())?"spade":c[1])+" and "+(/d,[dh]/.test(c)?"club":c[0]) \$\endgroup\$
    – tsh
    Jan 11 at 3:51

Jelly, 34 bytes

ṢṚµĖ41,3ḥⱮỊẸoḂƲȧ"ȯ"“ɓ¤PⱮ»Ḳ¤j“ and 

A full program that takes a single list of two strings and prints the result to STDOUT.

Thanks to @JonathanAllan for suggesting a technique that ultimately saved a byte!

Alternative Jelly, 35 bytes

ṢṚµOḢ€ọ2¬Ẹo_J$ƲḂȧ"ȯ"“ɓ¤PⱮ»Ḳ¤j“ and 

A full program that takes a single list of two strings and prints the result to STDOUT.

Thanks to @JonathanAllan for pointing out a bug!

This works because of the following pattern:

║ First character           ║ c  ║ d   ║ h   ║ s   ║
║ Codepoint                 ║ 99 ║ 100 ║ 104 ║ 115 ║
║ ọ2                        ║ 0  ║ 2   ║ 3   ║ 0   ║
║ Subtract 1, or not, mod 2 ║ 1  ║ 1   ║ 0   ║ 1   ║
║ Subtract 2, or not, mod 2 ║ 1  ║ 0   ║ 1   ║ 1   ║


Ṣ                                    | Sort
 Ṛ                                   | Reverse
  µ                                  | Start a new monadic chain
   O                                 | Convert to codepoints
    Ḣ€                               | Head of each
      ọ2                             | Number of times divisible by 2
              Ʋ                      | Following as a monad:
        ¬Ẹ                           | - Any non-zero
          o_J$                       | - Or (the result of ọ2 from before minus the indices)
               Ḃ                     | Mod 2
                ȧ"                   | And zipped (with the reverse sorted input)
                  ȯ"“ɓ¤PⱮ»Ḳ¤         | Or zipped with "spade club" split at spaces
                            j“ and   | Join with " and " (the last ” is implicit)
  • 1
    \$\begingroup\$ @JonathanAllan thanks. I’d made a mistake in the bit after the ọ2 that I’d somehow failed to spot. Unfortunately I don’t think the corrected version easily supports your nice hash. I’ve found a hash that does work with this (using Ė41,3ḥⱮỊẸoḂƲ) which is one byte shorter so going with that! \$\endgroup\$ Jan 11 at 20:24

Perl 5 -n, 77 bytes

$,=" and ";/[dt] [dh]/&&s/heart/spade/+s/diamond/club/;say reverse sort/\S+/g

Try it online!

  • \$\begingroup\$ Heart + Diamond is wrong; /[dt] [dh]/ fixes it. \$\endgroup\$
    – Neil
    Jan 11 at 0:58
  • \$\begingroup\$ @Neil Thanks! I missed that when I reviewed my output. Fixing it saved a few bytes, too. \$\endgroup\$
    – Xcali
    Jan 11 at 5:46

Charcoal, 52 49 bytes

F²⊞υS⪫E⌈⟦υ⮌υ⟧⎇›⁼§hdκ§ι⁰⊙sc№Συλ§⪪spadeclub⁵κι and 

Try it online! Link is to verbose version of code. Explanation:


Input the two strings.

E⌈⟦υ⮌υ⟧⎇›⁼§hdκ§ι⁰⊙sc№Συλ§⪪spadeclub⁵κι and 

Sort them in descending order, then unless one the two strings contains s or c, change the first string from heart to spade and the second from diamond to club, then join the results with and.


Uiua, 76 72 bytes

$"_ and _"⍜(⊟∩□|⊏⍖.)(∘|(⊙⊙;|⊙;)≍,,∩(("club"|"spade")=@h⊢),)×∩(∊:"hd"⊢),,

Test pad

Naïve solution to the problem (if anyone can golf this more, comment please)


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.