-2
\$\begingroup\$

Anyone who has spent any time around a deck of playing cards will recognize the riffle shuffle. The deck is cut in half and the two stacks are riffled simultaneously into the same pile before being tidied up in a sometimes visually appealing way.

This code-golf challenge is to write a function/method/(language equivalent) that performs the riffle shuffle on an array/stack/(language equivalent) of any size in the language of your choice.

As input, your function will except an array (language equivalent), plus how many times to run the shuffle. When done, it will return the shuffled array.

Your riffle shuffle function must implement the following algorithm:

  1. Divide the deck into two stacks

    A stack must have a minimum of 40% of the total cards in the deck and a maximum of 60%

  2. Choose a random stack to start with

  3. Drop 1 - 7 cards from the bottom of the starting stack to the top of the newly shuffled deck

  4. Drop 1 - 7 cards from the bottom of the other stack to the top of the newly shuffled deck

  5. Repeat #3 and #4 until only one stack remains

  6. Drop the remaining cards from the remaining stack on top of the newly shuffled deck

Smallest character count will be chosen as the answer in 1 week (May 29th).

This is the sample deck of cards to use:

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

Your answer should contain:

  • Code-golfed code
  • What the sample deck looks like after being shuffled twice
  • Un-golfed code
\$\endgroup\$
5
  • 3
    \$\begingroup\$ I've removed the extraneous [popularity-contest] here as it's not part of the scoring. Also, I've removed the langauge restrictions - we usually like to let everyone play instead of discouraging some from submitting an answer in a language they prefer. \$\endgroup\$
    – Doorknob
    Commented May 22, 2014 at 19:48
  • 3
    \$\begingroup\$ Two things: Firstly, you should explicitly specify that steps 1, 3 and 4 are subject to randomness (and possibly a uniform distribution, if you want to enforce that). Secondly, I don't think requesting the output of a random process helps much here, because it doesn't really prove the implementation is correct and will just clutter this post. \$\endgroup\$ Commented May 22, 2014 at 19:58
  • \$\begingroup\$ Can I expect the deck to always have an even number of cards, or not? \$\endgroup\$
    – Οurous
    Commented May 22, 2014 at 23:45
  • 1
    \$\begingroup\$ This challenge would be interesting if it didn't give the step-by-step algorithm the code must implement. As is, the only competition is in how well you golf the operations (and what language you use). \$\endgroup\$
    – xnor
    Commented May 23, 2014 at 3:14
  • \$\begingroup\$ @Ourous even or odd number of cards \$\endgroup\$
    – zoplonix
    Commented May 23, 2014 at 13:45

4 Answers 4

1
\$\begingroup\$

Python (131)

Waaaay too long, even for something that came to be after a "careful" reading of the rules:

Drop 1 - 7 cards from the bottom of the starting stack to the top of the newly shuffled deck

Doens't actually say this should be random, so I'll just always drop 1 card.

Divide the deck into two stacks

A stack must have a minimum of 40% of the total cards in the deck and a maximum of 60%

Sure. I'll just always do about 50%.

Anyways, the code:

def s(d):
 b=[d.pop()for _ in range(len(d)/2)];r=[];b,d=(b,d)if id(4)%2 else(d,b)
 while b and d:r+=[b.pop(),d.pop()]
 return r+b+d

Sample output:

In [17]: s(s([
    ...: 'AH', '2H', '3H', '4H', '5H', '6H', '7H', '8H', '9H', '10H', 'JH', 'QH', 'KH',
    ...: 'AC', '2C', '3C', '4C', '5C', '6C', '7C', '8C', '9C', '10C', 'JC', 'QC', 'KC',
    ...: 'KD', 'QD', 'JD', '10D', '9D', '8D', '7D', '6D', '5D', '4D', '3D', '2D', 'AD',
    ...: 'KS', 'QS', 'JS', '10S', '9S', '8S', '7S', '6S', '5S', '4S', '3S', '2S', 'AS'
    ...: ]))
Out[17]: 
['AD',
 'KH',
 'AC',
 'KS',
 '2D',
 'QH',
 '2C',
 'QS',
 '3D',
 'JH',
 '3C',
 'JS',
 '4D',
 '10H',
 '4C',
 '10S',
 '5D',
 '9H',
 '5C',
 '9S',
 '6D',
 '8H',
 '6C',
 '8S',
 '7D',
 '7H',
 '7C',
 '7S',
 '8D',
 '6H',
 '8C',
 '6S',
 '9D',
 '5H',
 '9C',
 '5S',
 '10D',
 '4H',
 '10C',
 '4S',
 'JD',
 '3H',
 'JC',
 '3S',
 'QD',
 '2H',
 'QC',
 '2S',
 'KD',
 'AH',
 'KC',
 'AS']

This is actually the code as I wrote it, I didn't specifically golfed any code. If you just want an explanation, please say so.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Golfed it down to 84 chars: s=lambda d:sum(map(list,zip(*([d.pop()for _ in d[:len(d)/2]],d)[::id(4)%2*2-1])),[]). You basically want to get your two lists, zip them, then flatten them; that is what I implemented. \$\endgroup\$
    – Justin
    Commented May 22, 2014 at 23:48
  • \$\begingroup\$ Golfed it down to 77 chars: s=lambda d:sum(map(list,zip(*[d[:len(d)/2],d[len(d)/2:]][::id(4)%2*2-1])),[]) \$\endgroup\$
    – Justin
    Commented May 23, 2014 at 4:20
  • 1
    \$\begingroup\$ Actually, we missed something: "As input, your function will except [sic] ... how many times to run the shuffle" \$\endgroup\$
    – Justin
    Commented May 23, 2014 at 4:23
  • \$\begingroup\$ id(x)%2 will always be 0 because memory addresses are aligned on 4-byte boundaries. \$\endgroup\$
    – Claudiu
    Commented May 23, 2014 at 4:51
0
\$\begingroup\$

Cobra - 307

Don't have access to a compiler atm, so this should work, but I'll be able to check later.

def f(d,n) as List<of int>
    r=Random()
    x=d.count
    for m in n
        p=q=[]
        for c in x
            if c%2>0,p.add(d.pop)
            else,q.add(d.pop)
        if r.next(0,2)>0,a,b=p,q
        else,a,b=q,p
        for c in x
            for z in r.next(0,7),if a.count>0,d.add(a.pop)
            for z in r.next(0,7),if b.count>0,d.add(b.pop)
    return d
\$\endgroup\$
0
\$\begingroup\$

Python 84

Golfed:

def s(d):
 e=len(d)/2;B=d[:e];C=d[e:];D=[]
 for x in range(e):D+=B[x],C[x]
 return D

Output Deck:

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

Un-golfed:

def Shuffle(Deck):
    Stack1 = Deck[:len(Deck)/2]            # 2nd Half of Deck
    Stack2 = Deck[len(Deck)/2:]            # 1st Half of Deck
    Output = []                            # Initialize Output List
    for index in range(len(Deck)/2):
        Output.append(Stack1[index])       # Append Output List with element from Stack1
        Output.append(Stack2[index])       # Append Output List with element from Stack2
    return Output                          # Return Output

Uses the same loopholes as @synthetica.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You missed one thing: "Choose a random stack to start with" \$\endgroup\$
    – Justin
    Commented May 23, 2014 at 4:13
  • 1
    \$\begingroup\$ Actually, we missed something else: "As input, your function will except [sic] ... how many times to run the shuffle" \$\endgroup\$
    – Justin
    Commented May 23, 2014 at 4:25
  • \$\begingroup\$ @Quincunx Oh, that wasn't in the list but I see it now, I'll work on this later... \$\endgroup\$ Commented May 23, 2014 at 7:45
0
\$\begingroup\$

Python, 69 chars (actually takes number of times to shuffle as input)

If one follows the algorithm, always picking 1 card at each step of 1-7 cards (as it wasn't explicitly said to have to be random), then with an array like:

[1, 2, 3, 4, 5, 6]

We have one of two results depending on which stack is picked first:

[1, 2, 3] [4, 5, 6] ==> [1, 4, 2, 5, 3, 6]
[4, 5, 6] [1, 2, 3] ==> [4, 1, 5, 2, 6, 3]

The following algorithm accomplishes this n times, using id(b)%9>4 as a source of binary randomness[1]:

def s(d,n):
 for i in range(n):b=d[:];F=id(b)%9>4;d[F::2]=b[26:];d[1-F::2]=b[:26]

Sample output:

>>> o = ['AH', '2H', '3H', '4H', '5H', '6H', '7H', '8H', '9H', '10H', 'JH', 
 'QH', 'KH', 'AC', '2C', '3C', '4C', '5C', '6C', '7C', '8C', '9C', '10C', 'JC',
 'QC', 'KC', 'KD', 'QD', 'JD', '10D', '9D', '8D', '7D', '6D', '5D', '4D', '3D', 
 '2D', 'AD', 'KS', 'QS', 'JS', '10S', '9S', '8S', '7S', '6S', '5S', '4S', '3S',
 '2S', 'AS']
>>> d = o[:]; s(d, 2); d
['KD', 'KS', 'AH', 'AC', 'QD', 'QS', '2H', '2C', 'JD', 'JS', '3H', '3C', '10D', '10S', '4H', '4C', '9D', '9S', '5H', '5C', '8D', '8S', '6H', '6C', '7D', '7S', '7H', '7C', '6D', '6S', '8H', '8C', '5D', '5S', '9H', '9C', '4D', '4S', '10H', '10C', '3D', '3S', 'JH', 'JC', '2D', '2S', 'QH', 'QC', 'AD', 'AS', 'KH', 'KC']
>>> d = o[:]; s(d, 2); d
['AC', 'AH', 'KS', 'KD', '2C', '2H', 'QS', 'QD', '3C', '3H', 'JS', 'JD', '4C', '4H', '10S', '10D', '5C', '5H', '9S', '9D', '6C', '6H', '8S', '8D', '7C', '7H', '7S', '7D', '8C', '8H', '6S', '6D', '9C', '9H', '5S', '5D', '10C', '10H', '4S', '4D', 'JC', 'JH', '3S', '3D', 'QC', 'QH', '2S', '2D', 'KC', 'KH', 'AS', 'AD']

[1] This gives about a 44.4%/55.5% skew:

>>> r = {0: 0, 1: 0}
>>> for i in range(1000000):
        r[int(id(i)%9>4)]+=1
>>> r
{0: 555517, 1: 444483}

For two extra characters we can get a much better 50.5%/49.5% result:

>>> r = {0: 0, 1: 0}
>>> for i in range(1000000):
        r[int(id(i)%99>49)]+=1
>>> r
{0: 505050, 1: 494950}
\$\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.