Wanna See a Card Trick? (Part I)

5

4

Amazingly, this is the easier of the three card tricks I know off the top of my head...

The aim of this is to have your compiler perform a specific card trick. There's no slight of hand, and the compiler won't be memorizing the choice and saying "Voila, this is your card!" The code will basically manipulate a stack of cards and the final card drawn from this stack will be the card chosen at random:

If you want to understand this trick further, feel free to follow this with an actual deck of cards so that you can learn the trick. I will be displaying the order of the cards in the face-down stack in my example in curly braces {} so that you can see what's happening.

The standards set in this trick:

  1. A standard deck of cards is generated, 52 cards (no jokers required). From this deck, nine cards will be chosen at random to form our trick's card stack.

  2. The backs of the cards will be displayed as @@.

  3. The face-size of the cards will be displayed in the format XY where X is the value, A-9,T,J,Q,K (T = 10); and Y is the suit, Spades, Clubs, Diamonds, Hearts. So AS for the Ace of Spades, TC for 10 of Clubs, 8H for the 8 of Hearts, etc.

  4. In displaying the stack of cards, from left to right, the left-most card will be located on the bottom of the stack, and the right-most card will be at the top of the stack. Similarly, if cards are in smaller sets, left-most = bottom card, right-most = top card.

Given these standards, my randomly chosen stack for this example looks like this: @@ @@ @@ @@ @@ @@ @@ @@ @@ (cards facing down)

...And when facing up: TD JD 8C 7D 8S 3C QH 9S 3S

Note, this means my facing up stack has the ten of diamonds on the bottom, and the three of spades at the top.

Your deck may vary from mine (see Standards 1 above re random generated stack)

I will go through this trick step-by-step, and how the code needs to work:

  • Accept a number between 1 and 9 as input, to be used later on:

2

  • Generate your nine-card stack and display the cards face down first, in sets of 3, four spaces in between each set. This is so that the user can see they've chosen a specific card out of a specific set:

@@ @@ @@ @@ @@ @@ @@ @@ @@

  • Flip the cards over, so that the user can see which card they chose:

TD JD 8C 7D 8S 3C QH 9S 3S

  • Announce the card chosen, full wording of the card, e.g. the second card (derived from our input of 2 earlier on):

JACK OF DIAMONDS

  • Take the chosen card and place it on top of that specific set, facing up; remembering that the right-most card in each set is the top-most in each set facing up:

TD 8C JD 7D 8S 3C QH 9S 3S

  • Put the other two sets on top of the set with the chosen card, also facing up, to form one stack. It does not matter which of the two sets goes first:

TD 8C JD 7D 8S 3C QH 9S 3S

  • Flip the stack over so that the cards are facing down:

@@ @@ @@ @@ @@ @@ @@ @@ @@

Note: At this point, the stack of cards will have now reversed in order:

{3S 9S QH 3C 8S 7D JD 8C TD}

  • Our ten of diamonds is on the top of the pile now... And our chosen card is third from the top... The chosen card will ALWAYS be third from the top at this point.

  • Now, we have to spell out the card in question, in our case the JACK OF DIAMONDS. Cards are dealt from the top of the deck to another pile, spelling out the card as we go. After the spelling of each word, the rest of the pile goes straight on top with each word. I've shown how the cards in the face-down stack are ordered after each word in curly braces:

J @@ A @@ C @@ K @@, @@ @@ @@ @@ @@ {TD 8C JD 7D 3S 9S QH 3C 8S}

O @@ F @@, @@ @@ @@ @@ @@ @@ @@ {8S 3C TD 8C JD 7D 3S 9S QH}

D @@ I @@ A @@ M @@ O @@ N @@ D @@ S @@, @@ {QH 9S 3S 7D JD 8C TD 3C 8S}

  • Here's what they call the prestige, the final part of the trick. Deal out the first five cards from the top of the stack, face down to the words HERE'S THE <NUMBER> OF <SUIT>! <FIFTH CARD FACE UP>, flipping the final card to show face up...

HERE'S @@ THE @@ JACK @@ OF @@ DIAMONDS! JD

The fifth card from the stack should now be the card originally chosen.

Example output, using a new randomly chosen stack, and 4 as the input.

@@ @@ @@    @@ @@ @@    @@ @@ @@
3D AD JS    TH KD QS    JC 6D 4S
TEN OF HEARTS
3D AD JS    KD QS TH    JC 6D 4S
KD QS TH 3D AD JS JC 6D 4S
@@ @@ @@ @@ @@ @@ @@ @@ @@
T @@ E @@ N @@, @@ @@ @@ @@ @@ @@
O @@ F @@, @@ @@ @@ @@ @@ @@ @@
H @@ E @@ A @@ R @@ T @@ S @@, @@ @@ @@
HERE'S @@ THE @@ TEN @@ OF @@ HEARTS! TH

Please note, the final card you are producing at the end is pulled from the card stack (array), and will always be the fifth card in the stack, not from some assigned variable; and the code needs to reflect this. Note, that if you're dealing with a zero-based array language that this would mean, element 4, as opposed to element 5 in a one-based array language.

The key to this code-golf (yes, this is going to be code-golf, muahahahahaha!) is through the manipulation of the nine-card stack. With each word spelled out, the affected cards at the top of the stack will be reversed, thrust to the bottom of the stack and the remaining cards will be placed on top; refer to the examples above to see how that works. Run through the logic with nine playing cards if you have to in order to understand how it works.

Rules

  1. This is code-golf. Lowest byte-count will win; in the event of a tie in byte count, highest votes will win.
  2. No silly loopholes.
  3. The input can be implemented in whatever way you see fit: STDIN, an array, a parameter in a function, whatever takes your fancy...
  4. Please provide a link to your executing code on an online IDE like TIO so that we can marvel at your work. Learning from one another is something I encourage, and I'd love to see how you all can code this up!
  5. The chosen card is drawn correctly at the end providing you have the array/stack manipulations worked out. Please do not simply assign the chosen card into a variable and pull it out in the end... This will be regarded as an invalid answer.

WallyWest

Posted 2018-02-09T02:15:41.443

Reputation: 6 949

This is a really, really interesting challenge to golf. – Οurous – 2018-02-12T21:53:47.153

I'm glad you approve @Ourous, looking forward to seeing your entry! – WallyWest – 2018-02-12T22:24:59.187

Is trailing whitespace allowed? – Οurous – 2018-02-12T23:07:23.527

It's up now, enjoy! (and also, I'd like to know if the output method is acceptable) – Οurous – 2018-02-13T00:29:37.240

Answers

1

Perl 5, 551 549 547 546 + 1 (-p) = 547 bytes

%r=(T,TEN,J,JACK,Q,QUEEN,K,KING,A,ACE);map$r{++$.}=$_,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE;map{/./;$u{$_.$&}=[$r{$_},OF,$&.$']for keys%r}DIAMONDS,HEARTS,SPADES,CLUBS;@0=(keys%u)[0..8];$x.="@0[$_..$_+2]   ",print'@@ 'x3,$"x2for@z=(0,3,6);@w=@{$u{$0[$_]}};say"
$x
@w";@t=@0[($l=$_-$_%3)..$l+2];splice@t,$_%3,1;push@t,$0[$_];@0[$l..$l+2]=@t;print"@0[$_..$_+2]   "for@z;@t=splice@0,$l,3;say"
@t @0
".'@@ 'x9;@0=reverse@t,@0;map{@t=();push@t,pop@0for/./g;say+(join$q=' @@ ',/./g),' @@,',' @@'x@0;@0=(@t,@0)}@w;$_=(join$q,"HERE'S",THE,@w)."! $0[4]"

Try it online!

Uses 0-based counting, so the cards are numbered 0-8.

Xcali

Posted 2018-02-09T02:15:41.443

Reputation: 7 671

Great submission but line 6 seems to only shows the back of six cards instead of nine...? – WallyWest – 2018-02-13T21:24:15.963

1You're right. I messed that up while I was golfing the code. It's fixed now. – Xcali – 2018-02-13T21:53:56.100

BTW, thanks for detailing the 0-based array, did this help with golfing it down? – WallyWest – 2018-02-15T23:23:47.487

1Saved 5 bytes. Would have needed an extra $_--; in there otherwise. – Xcali – 2018-02-15T23:53:12.230

7

Python 2, 593 589 bytes

from random import*
N=input()-1
n='\n';A='@@ ';V='A23456789TJQK';Z='SCDH'
J=' '.join
j='    '.join
s=sample(map(''.join,zip(V*4,Z*13)),9)
x,y=s[N]
S=[s[:3],s[3:6],s[6:]]
x,y=dict(zip(V,'ACE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN JACK QUEEN KING'.split()))[x],dict(zip(Z,'SPADES CLUBS DIAMONDS HEARTS'.split()))[y]
print(A*3+'   ')*3+n+j(map(J,S))+n+x,'OF',y
S[N/3]+=S[N/3].pop(N%3),
print j(map(J,S))
s=S.pop(N/3)+S[0]+S[1]
print J(s)+n+A*9;s=s[::-1]
for w in x,'OF',y:l=len(w);s=s[:~l:-1]+s[:-l];print' @@ '.join(w)+' @@, '+-l%9*A
print"HERE'S @@ THE %s @@ OF %s! %s"%(A+x,A+y,s[4])

Try it online!

-4 bytes thanks to ovs

TFeld

Posted 2018-02-09T02:15:41.443

Reputation: 19 246

1

Clean, 764 ... 686 bytes

import StdEnv,Math.Random,System._Unsafe,Text,System.Time
f=["","","   ":f]
w=" "
^ ="@@"
$s=g[hd u+t\\u<-s&t<-f]
d=reverse
r=repeatn 9
j=join
g=j w
s=split w
?n#n=n-1
#!a=removeDup[[[w<+y.[0],x,"OF",y]\\w<-:"A123456789TJQK"&x<-s"ACE ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN JACK QUEEN KING",y<-s"CLUBS HEARTS DIAMONDS SPADES"]!!(i rem 52)\\i<-genRandInt(toInt(accUnsafe time))]%(0,8)
#v=a!!n
#b=insertAt(n/3*3+2)v(removeAt n a)
#c=b%(n/3,n/3+2)
#c=c++removeMembers b c
#v=tl v
#(z,s)=foldl(\(c,s)k=let(p,q)=splitAt(9-size k)c in(d q++p,[j"@@ "[e<+w\\e<-:k]+j^["@@, ":[w\\_<-p]]:s]))(d c,[g(r^),g(map hd c),$b,g v,$a,$(r[^])])v
#[x:y]=z!!4
=d[j" @@ "["HERE'S","THE":y]+"! "+x:s]

Try it online!

Defines the function ? :: Int -> [String], taking the card number and returning a list of lines.

Explanation coming when answer is finalized so I don't need to keep retyping it

Οurous

Posted 2018-02-09T02:15:41.443

Reputation: 7 916

What does ?n#n do? – Esolanging Fruit – 2018-02-13T00:59:07.987

@EsolangingFruit It's actually two statements, the function definition ?n, and the node expression #n=n-1. The second of which effectively subtracts 1 from n. – Οurous – 2018-02-13T01:13:03.653

So # is not a prefix operator but actually away to introduce non-recursive bindings? – Esolanging Fruit – 2018-02-13T01:18:07.627

@EsolangingFruit Yep. Essentially an imperative assignment, with the exception of functions which can still recurse when used in # expressions. – Οurous – 2018-02-13T01:29:55.950

Interesting approach, though I'm wondering if you may have done yourself an injustice with using a language that doesn't appear very golfable? – WallyWest – 2018-02-13T02:17:39.890

@WallyWest It can do.. okay. I enjoy writing well-golfed, but long answers more than short and easily-golfed ones. – Οurous – 2018-02-13T02:33:11.390

1I meant no disrespect, @Ourous... It's a great submission, don't get me wrong... I guess having code-golfed a fair bit, I've been so used to seeing code that isn't so... tidy! ;) Look forward to later golfs of this piece when you have the time :) – WallyWest – 2018-02-13T02:35:57.733