17
\$\begingroup\$

The first magic card trick I ever learned as a child was the following:

  • Have 1 deck of cards where the pattern on the back is not vertically symmetric.
  • Organize all cards to be facing one direction.
  • Ask an individual to, "pick a card, any card, memorize it and give it back to you".
  • Proceed to put it into the deck (in the wrong direction).
  • Shuffle vigorously, giving the illusion that you won't know where their card is.
  • Produce their card to their amazement.

This trick is obviously a little bit lack-luster in nature now-a-days, however it makes for a good challenge. Write a program, that when given no input, outputs a randomly shuffled deck of cards with one of the cards, chosen at random, reversed. However, when the input is a deck of cards with one card reversed, you must output the reversed card (in the correct order).


The Deck of Cards

A deck of cards is defined to be:

[2S,3S,4S,5S,6S,7S,8S,9S,TS,JS,QS,KS,AS,
 2D,3D,4D,5D,6D,7D,8D,9D,TD,JD,QD,KD,AD,
 2H,3H,4H,5H,6H,7H,8H,9H,TH,JH,QH,KH,AH,
 2C,3C,4C,5C,6C,7C,8C,9C,TC,JC,QC,KC,AC]

A card is defined as it's number, then the first letter of its suit. The reverse of a card is the exact opposite, the first letter of its suit followed by a number.

The Drawn Card

Example, if the card we randomly chose to reverse was the 4 of Clubs (4C), we'd end up with (without shuffling, obviously):

[2S,3S,4S,5S,6S,7S,8S,9S,TS,JS,QS,KS,AS,
 2D,3D,4D,5D,6D,7D,8D,9D,TD,JD,QD,KD,AD,
 2H,3H,4H,5H,6H,7H,8H,9H,TH,JH,QH,KH,AH,
 2C,3C,C4,5C,6C,7C,8C,9C,TC,JC,QC,KC,AC]

The Shuffling

Then, after shuffling:

[2H,2C,6S,4D,QH,6C,TD,8C,7H,5H,C4,3D,7S,7C,KC,QD,QC,JS,7D,6D,2S,5C,KD,3C,3S,2D,8H,KH,6H,AH,8S,JH,TS,AD,5D,9H,4H,JD,QS,4S,JC,3H,8D,TC,AS,TH,KS,AC,9C,9S,5S,9D]

This is a valid output given empty input.

The Deck Input

However, conversely, when our program receives the above output as input, it should output 4C. That is to say, for an input of:

[2H,2C,6S,4D,QH,6C,TD,8C,7H,5H,C4,3D,7S,7C,KC,QD,QC,JS,7D,6D,2S,5C,KD,3C,3S,2D,8H,KH,6H,AH,8S,JH,TS,AD,5D,9H,4H,JD,QS,4S,JC,3H,8D,TC,AS,TH,KS,AC,9C,9S,5S,9D]

You iterate through until you find the reversed card, and return it, reversed back to the normal state. So here we'd find C4, know that C isn't a number, and return it as 4C, which is correct.


Rules

  • You may not load the deck from any external sources.
  • An empty input should result in a randomly shuffled deck with 1 random card reversed.
  • A deck of cards with 1 card reversed as input should result in the reversed card.
  • Any other inputs can result in explosive llamas riding segways through a futuristic tube.
    • Or anything else, for that matter.
  • Both the chosen card and the shuffling order must be uniformly random.
    • I.E. all cards have equal chance of being selected to be reversed.
    • I.E. all combinations of cards have an equal chance of appearing.
  • You may use SHCD or shcd for the suits, but be consistent:
    • If you choose uppercase suits (SHCD) you must also use TJQKA.
    • If you choose lowercase suits (shcd) you must also use tjqka.
  • This is , winner is lowest bytes.
\$\endgroup\$
11
  • 2
    \$\begingroup\$ @labela--gotoa there's FAR too many variations of this haha. I remember my dad blowing my mind using vertically symmetric cards and doing a different trick, but making me think it was this one. \$\endgroup\$ Feb 20, 2018 at 21:35
  • 13
    \$\begingroup\$ "Explosive llamas riding segways through a futuristic tube" - I'm looking forward to your next ascii-art challenge... \$\endgroup\$ Feb 20, 2018 at 22:05
  • 3
    \$\begingroup\$ Rotating the entire deck by a random offset from 0 to 51 inclusive satisfies the condition that "all cards have an equal chance of appearing anywhere in the shuffled deck", but should probably not be considered a random shuffling. Do you mean that all (52!) orders are approximately equally likely? \$\endgroup\$
    – aschepler
    Feb 21, 2018 at 1:02
  • 1
    \$\begingroup\$ Just to extend on what @aschepler said: with the period length of the default PRNG in many languages, most of the 52! possible shuffles have a probability of appearing exactly equal to zero (although it might be better or worse depending on the shuffling algorithm). \$\endgroup\$
    – Arnauld
    Feb 21, 2018 at 11:47
  • 1
    \$\begingroup\$ Is a dalai lama riding a lama on a dolly also acceptable? I'm out of segways and explosives, but I have got candy worms... i.imgur.com/gEkVR5P.gif \$\endgroup\$ Feb 21, 2018 at 12:01

11 Answers 11

7
\$\begingroup\$

Retina, 61 60 59 bytes

G`[HCDS].
^$
23456789TJQK
/^2/&L$`.
$&H¶$&D¶$&C¶$&S
@V`
O?`

Try it online! Edit: Saved 1 2 bytes thanks to @MartinEnder. Explanation:

G`[HCDS].

Delete all unreversed cards. This should leave one reversed card or no cards.

^$
23456789TJQK
/^2/&L$`.
$&H¶$&D¶$&C¶$&S

If the input is (now) empty, create a pack of cards.

@V`

Randomly select one card and reverse it (unreverses the single reversed card).

O?`

Shuffle the card(s).

\$\endgroup\$
0
4
\$\begingroup\$

05AB1E, 29 bytes

Y9ŸJ.•§®т•«.•öB•âsKDgiëDΩÂ:.r

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ .•Āk{?Öw•9LJì#`â would save a few bytes to compress those two together. \$\endgroup\$ Feb 21, 2018 at 14:08
  • \$\begingroup\$ @MagicOctopusUrn: After removing 1 and 2, that ends up at the same bytecount doesn't it? \$\endgroup\$
    – Emigna
    Feb 21, 2018 at 14:26
  • \$\begingroup\$ Try it online! - 28, right? \$\endgroup\$ Feb 21, 2018 at 15:30
  • \$\begingroup\$ @MagicOctopusUrn: Unfortunately not. You've got both 1 and a in there. \$\endgroup\$
    – Emigna
    Feb 21, 2018 at 20:28
  • \$\begingroup\$ Leave it to me to misinterpret Y9ŸJ as 9LJ \$\endgroup\$ Feb 21, 2018 at 21:30
3
\$\begingroup\$

PowerShell v2 or later, 175 bytes

%{$s=[char[]]'SDHC';if($_){$_|?{$s-contains$_[0]}|%{$_[1]+$_[0]}}else{$d=$s|%{$e=$_;[char[]]'23456789TJQKA'|%{$_+$e}}|random -c 52;$r=random 52;$d[$r]=$d[$r][1]+$d[$r][0];$d}}

Long version:

ForEach-Object {
    $s = [char[]]'SDHC'                         # Create a character array with the suits
    if ($_) {                                   # If there's pipeline input ...
        $_ |                                    # ... write it to the output pipeline ...
            Where-Object {$s -contains $_[0]} | # ... but let only those input elements pass where the first letter appears in the suits ...
            ForEach-Object {$_[1] + $_[0]}      # ... and swap the two elements
    } else {
        $d = $s | ForEach-Object {              # Assign $d to the output of the suits, processing each element first.
                $e = $_                         # Store the current suit element for use in the inner loop
                [char[]]'23456789TJQKA' | ForEach-Object {$_ + $e}  # Process each of the numbers, joining it with the current suit, ...
            } | Get-Random -Count 52            # ... and the resulting 2-char-strings goes back into the output to be shuffled
        $r = Get-Random -Maximum 52
        $d[$r] = $d[$r][1] + $d[$r][0]          # Swap the two chars of a random array element in $d
        $d                                      # Write $d to the output pipeline
    }
}

Usage:

Create a shuffled deck and store it in a variable:

$Deck = %{$s=[char[]]'SDHC';if($_){$_|?{$s-contains$_[0]}|%{$_[1]+$_[0]}}else{$d=$s|%{$e=$_;[char[]]'23456789TJQKA'|%{$_+$e}}|random -c 52;$r=random 52;$d[$r]=$d[$r][1]+$d[$r][0];$d}}

Inspect the variable at will, for example

$Deck -join ','

Pipe the deck back into the script:

$Deck | %{$s=[char[]]'SDHC';if($_){$_|?{$s-contains$_[0]}|%{$_[1]+$_[0]}}else{$d=$s|%{$e=$_;[char[]]'23456789TJQKA'|%{$_+$e}}|random -c 52;$r=random 52;$d[$r]=$d[$r][1]+$d[$r][0];$d}}
\$\endgroup\$
0
2
\$\begingroup\$

Python 2, 175 bytes

from random import*
s='SHCD';c='23456789TJQKA'
d=input()
if d:print[b+a for a,b in d if a in s];q
k=sample
r=k(c,1)+k(s,1)
print k([(a+b,b+a)[r==a+b]for a in c for b in s],52)

Try it online! empty input is denoted as []

\$\endgroup\$
2
\$\begingroup\$

><>, 215 193 bytes

i:0)?\~"CHSD":"2"$:"3"$:"4"$:"5"$:"6"$:"7"$:"8"$:"9"$:"T"$:"J"$:"Q"$:"K"$:"A"$&105&"S"=?.~~~{c0.
=+i$?\i$:::"B")$"I"(*$"S"
_oo$~/;
x0
x0
x0
x0
x0
x0
x0
x0
x0
x0
\l&>?!<
>&"3"%:?\~$>o<
\  }}&-1/

Try it online!

Takes input as not separated cards, and output as the same (e.g. KCAC5C6S...)

To make it easier to test, here's a version that takes input as comma separated and outputs as newline separated.

All the x0s are just an attempt to make a semi-uniform random number generator. More of them increases the range of possible values, and the opposite for less. 10 of them is where I judged it to be random enough.

Note that it follows the rules in that:

  • All cards have an equal chance of being selected to be reversed.
  • All cards have an equal chance of appearing anywhere in the shuffled deck.

But not all shuffled combinations are possible outputs (and in fact, the vast majority aren't).

\$\endgroup\$
2
\$\begingroup\$

Jelly, 26 bytes

9ḊṾ€;“AJKQT”p“CDHS”ḟ⁸ẊU-¦Ẋ

A monadic link accepting a list of lists of characters (a stub of 0 cards or a full-deck of 52 cards with one card reversed) and returning a list of lists of characters (a stub of the 1 reversed card but forward or a full-deck with one random card reversed).

Try it online! (footer to make input and output representations match - as a full program Jelly code Python-evals the argument and smashes the characters together for the output)

How?

9ḊṾ€;“AJKQT”p“CDHS”ḟ⁸ẊU-¦Ẋ - Link: list of lists of characters, Z
9Ḋ                         - nine dequeued = [2,3,4,5,6,7,8,9]
  Ṿ€                       - unevaluate €ach = ['2','3','4','5','6','7','8','9']
     “AJKQT”               - literal list of characters = ['A','J','K','Q','T']
    ;                      - concatenate = ['2','3','4','5','6','7','8','9','A','J','K','Q','T']
             “CDHS”        - literal list of characters = ['C','D','H','S']
            p              - Cartesian product = [['2','C'],['2','D'],...,['T','S']]
                           -   a full deck of forward cards
                    ⁸      - chain's left argument, Z
                   ḟ       - filter discard
                           -   leaving either that deck or the 1 reversed card in the input
                     Ẋ     - shuffle
                        ¦  - sparse application...
                       -   - ...to index: -1 (which doesn't exist when the length is only 1)
                      U    - ...do: upend (reverses the penultimate card of the deck)
                         Ẋ - shuffle
\$\endgroup\$
6
  • \$\begingroup\$ This seems to always reverse the ten of hearts. Shouldn't it be a random card? \$\endgroup\$
    – Emigna
    Feb 21, 2018 at 9:49
  • \$\begingroup\$ Ah, thanks, yes there is a bug - it can be fixed with an extra before the U (maybe I can fix for zero bytes instead) but will have to do it later... \$\endgroup\$ Feb 21, 2018 at 11:25
  • \$\begingroup\$ Since this is a function, I'm not sure if you can return [[number, suit]] instead of [number, suit] to represent a single card when the input is non-empty. \$\endgroup\$ Feb 21, 2018 at 12:52
  • \$\begingroup\$ Also, no, I don't think there's any 0-byte fix for that. \$\endgroup\$ Feb 21, 2018 at 12:57
  • \$\begingroup\$ @EriktheOutgolfer I don't see why not, a lonesome card is a stub (short deck) of just one card after all. \$\endgroup\$ Feb 21, 2018 at 19:56
1
\$\begingroup\$

Ruby, 95 (or 100) bytes

->n{s=(0..51).map{|i|"A23456789TJQK"[i/4]+"HCDS"[i%4]}
n[0]?s-n:s[rand 52].reverse!&&s.shuffle}

Given an empty array as input, returns the deck as an array of strings. Given a nonempty array as input, returns the flipped card as an array containing a single string. If the flipped card is required as a string rather than a single-element array containing a string, the following adds 5 bytes: change s-n to (s-n)[0]

Try it online!

The first line generates a standard deck. The second line breaks down as follows

 n[0]?                  #If the input array is not empty (contains a truthy first element)
  s-n:                  #Find the contents of s with the contents of n removed. The only card remaining from the standard deck corresponds to the flipped card in the input.
                        #ELSE 
  s[rand 52].reverse!&& #Flip one card in place in the array s. As the result is truthy, whatever is next will be returned.
 s.shuffle              #shuffle the deck and return the shuffled deck with one element flipped
}
\$\endgroup\$
1
\$\begingroup\$

Java 8, 275 274 259 bytes

import java.util.*;s->{if(s==null){List l=new Stack();char i=52,r=i,x,y;for(r*=Math.random();i-->0;y="23456789TJQKA".charAt(i%13),l.add(i==r?x+""+y:y+""+x))x="HSDC".charAt(i&3);Collections.shuffle(l);return l;}return s.replaceAll(".*,(.)([^HSDC]).*","$2$1");}

Input is a String, output is either a String or a java.util.List depending on the input.

Explanation:

Try it online.

import java.util.*;          // Required import for List, Stack and Collections
s->{                         // Method with String parameter and Object return-type
  if(s==null){               //  If the input is `null`:
    char i=52,               //   Index-integer
         r=i,                //   Random-integer
         x,y;                //   Temp characters
    List l=new Stack();      //   Create a List
    for(r*=Math.random();    //   Determine the random integer in the range (0;52]
        i-->0                //   Loop `i` 52 times:
        ;                    //     After every iteration:
         y="23456789TJQKA".charAt(i%13)
                             //      Set `y` to one of 23456789TJQKA based on `i` modulo-13
         ,l.add(i==r?        //      If the random integer equals the current `i`
                 x+""+y      //       Add the current card reversed
                :            //      Else:
                 y+""+x))    //       Add the current card as is
      x="HSDC".charAt(i&3);  //    Set `x` to one of HSDC based on `i` bitwise-AND 3
    Collections.shuffle(l);  //   Shuffle the generated Deck
    return l;}               //   And return this Deck as result
                             //  If the input was a Deck instead:
  return s.replaceAll(".*,(.)([^HSDC]).*",
                             //   Get the reversed card from the Deck,
            "$2$1");}        //   and output it non-reversed
\$\endgroup\$
1
\$\begingroup\$

Pyth, 45 bytes

J"CDHS"KO52=NsM.S*+c"AKQJT"1S9J|f}hTJQXNK_@NK

Takes the empty list for empty input.
Try it online

Explanation

J"CDHS"KO52=NsM.S*+c"AKQJT"1S9J|f}hTJQXNK_@NK
J"CDHS"                                        Save the suits as J.
       KO52                                    Save a random index as K.
           =NsM.S*+c"AKQJT"1S9J                Save a shuffled deck as N.
                                f}hTJQ         Find all cards with suit first.
                               |      XNK_@NK  If there aren't any, flip a card.
\$\endgroup\$
1
\$\begingroup\$

R, 177 171 bytes

function(l=1,F="(.)(.)",R="\\2\\1",S=sample)if(l>1)sub(F,R,grep("^[SDHC]",l,v=T))else{m=S(outer(c(2:9,"T","J","Q","K"),c("S","D","H","C"),paste0))
m[1]=sub(F,R,m[1])
S(m)}

Try it online!

Given empty input, (call f with no input), we default to l=1 and thus create a random permutation m of the deck. Assuming sample is truly random, there is an equal probability of any card being the first in this list. So we modify the first one, and then shuffle again, returning the list.

Reversing it, we look for a card starting with one of SDHC and reverse it.

\$\endgroup\$
1
\$\begingroup\$

Python 2, 135 bytes

from random import*
s=shuffle
d=zip('A23456789TJQK'*4,'SCDH'*13)
s(d)
D=input()
if D:d=list(set(D)-set(d))
d[0]=d[0][::-1]
s(d)
print d

Try it online!

Cards are tuples of (value,suit)

Empty input is []

\$\endgroup\$

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.