The Perfect Shuffle – Solution

A perfect shuffle splits a deck of cards in two. The second half is folded evenly into the first half, so that every other card comes from the first and last half of the deck, respectively. This type of shuffle is practically impossible in real life, but for a computer simulation it’s not that difficult.

Programmers use an array to simulate a deck of cards. You could craft a multidimensional array to represent the 13 cards of the 4 suits, though most game programmers use a 52-element int array for the deck. They simulate the cards and suits when the array is output.

Rather than go through a 52-card simulation for this month’s Exercise, I tasked you to perfectly shuffle the letters in the alphabet, A to Z, which is a 26-element char array. A single shuffle() function can do the job, but you must also count how many shuffles are required to restore the array to its original order. Therefore, two tasks are in order.

For my solution, I wrote the shuffle() function first. Its job is to split the deck in two, then rebuild the deck by alternating cards from the first half and second half. Here is my solution, which — warning — uses both array and pointer notation.

void shuffle(char *deck)
{
    char left[HALFDECK];
    char right[HALFDECK];
    int x;

    /* split the deck */
    for(x=0;x<HALFDECK;x++)
    {
        left[x] = *(deck+x);
        right[x] = *(deck+HALFDECK+x);
    }

    /* shuffle */
    for(x=0;x<HALFDECK;x++)
    {
        *(deck+(x*2)) = left[x];
        *(deck+(x*2)+1) = right[x];
    }
}

The char pointer variable deck is the alphabet or deck of cards. Arrays left[] and right[] are the two halves that must be shuffled together.

The first step is to copy the upper and lower parts of the deck to the two arrays. The initial for loop does that, using the constant HALFDECK to set the offset for the upper half of the deck/array.

After the left[] and right[] arrays are filled, the second step is to rebuild the deck array by alternating characters from left[] and right[]. The second for loop accomplishes this task by using its looping variable x as an offset. Variable x needs to increment only to the HALFDECK size because it fetches two cards at once:

(x*2) inserts cards from the left[] half of the deck into even positions.

(x*2)+1 inserts cards from the right[] half of the deck into odd positions.

The end result is that the alphabet goes from this:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

To this:

ANBOCPDQERFSGTHUIVJWKXLYMZ

The Exercise’s solution also involves counting shuffles until the string returns to its original state. To do that, in the main() function, I duplicate the string. That way the original is intact, and only the copy is shuffled. A strcmp() function is used in a do-while loop to determine when the shuffles need to stop. Then the number of shuffle count is displayed.

Click here to view my full solution. Here is sample output:

Original deck: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shuffle  1: ANBOCPDQERFSGTHUIVJWKXLYMZ
Shuffle  2: ATNHBUOICVPJDWQKEXRLFYSMGZ
Shuffle  3: AWTQNKHEBXUROLIFCYVSPMJGDZ
Shuffle  4: ALWITFQCNYKVHSEPBMXJUGRDOZ
Shuffle  5: ASLEWPIBTMFXQJCUNGYRKDVOHZ
Shuffle  6: AJSCLUENWGPYIRBKTDMVFOXHQZ
Shuffle  7: ARJBSKCTLDUMEVNFWOGXPHYQIZ
Shuffle  8: AVRNJFBWSOKGCXTPLHDYUQMIEZ
Shuffle  9: AXVTRPNLJHFDBYWUSQOMKIGECZ
Shuffle 10: AYXWVUTSRQPONMLKJIHGFEDCBZ
Shuffle 11: AMYLXKWJVIUHTGSFREQDPCOBNZ
Shuffle 12: AGMSYFLRXEKQWDJPVCIOUBHNTZ
Shuffle 13: ADGJMPSVYCFILORUXBEHKNQTWZ
Shuffle 14: AODRGUJXMBPESHVKYNCQFTIWLZ
Shuffle 15: AHOVDKRYGNUCJQXFMTBIPWELSZ
Shuffle 16: AQHXOFVMDTKBRIYPGWNEULCSJZ
Shuffle 17: AIQYHPXGOWFNVEMUDLTCKSBJRZ
Shuffle 18: AEIMQUYDHLPTXCGKOSWBFJNRVZ
Shuffle 19: ACEGIKMOQSUWYBDFHJLNPRTVXZ
Shuffle 20: ABCDEFGHIJKLMNOPQRSTUVWXYZ
It took a total of 20 shuffles to restore the deck.

Your solution can be different, but the number of shuffles required to restore a 26-card deck is constant at 20.

Leave a Reply