-1
\$\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\$
  • 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 May 22 '14 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\$ – Martin Ender May 22 '14 at 19:58
  • \$\begingroup\$ Can I expect the deck to always have an even number of cards, or not? \$\endgroup\$ – Οurous May 22 '14 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 May 23 '14 at 3:14
  • \$\begingroup\$ @Ourous even or odd number of cards \$\endgroup\$ – user1886419 May 23 '14 at 13:45
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\$
  • 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 May 22 '14 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 May 23 '14 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 May 23 '14 at 4:23
  • \$\begingroup\$ id(x)%2 will always be 0 because memory addresses are aligned on 4-byte boundaries. \$\endgroup\$ – Claudiu May 23 '14 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\$
  • 1
    \$\begingroup\$ You missed one thing: "Choose a random stack to start with" \$\endgroup\$ – Justin May 23 '14 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 May 23 '14 at 4:25
  • \$\begingroup\$ @Quincunx Oh, that wasn't in the list but I see it now, I'll work on this later... \$\endgroup\$ – Harry Beadle May 23 '14 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, privacy policy and cookie policy

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