Shuffle That Playlist

Recently, I created a playlist of songs on a certain online subscription service. I chose to shuffle the tunes, but found that one song in particular played more often than the others. My immediate thought was, “Why can’t the programmers design a shuffled playlist that doesn’t overplay the same song”? Rather than email the programmers, I thought I’d present the puzzle as this month’s Exercise.

The challenge is this (and I hope online music jukebox programmers are visiting this site):

  • Given a list of 20 songs, randomize their play order.
  • Ensure that each song doesn’t play within a range of 15 songs from itself.

I chose the value 15 because if you use 20, or the exact number of songs, the same block of 20 tunes repeats in the same pattern. By keeping a 15-song buffer, you ensure that the list is randomized enough to keep things interesting, though some tunes may still play more often than others. That’s okay.

To get your started, I present the following code. It lists 20 songs in the tune[] pointer array. A frequency[] array tracks how many times a tune plays based on its element number from the tune[] pointer array:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COUNT 20

int main()
{
    char *tune[COUNT] = {
        "Brandy", "Respect", "Hey Jude", "The Twist",
        "Uptown Funk", "Macarena", "Killer Queen", "Lady",
        "Foolish Games", "Call Me", "Royals", "The Sign",
        "Happy", "Billie Jean", "My Sharona", "Family Affair",
        "Hurts So Good", "Smooth", "Mack The Knife", "No One"
    };
    int frequency[COUNT];
    int t,play,cycle;

    /* initialize stuff */
    srand( (unsigned)time(NULL) );    /* seed the randomizer */
    for(t=0;t<COUNT;t++)            /* zero frequency counter */
        frequency[t] = 0;
    cycle = 0;                        /* counts to 100 */

    /* Randomly play the tunes and keep track */
    while(cycle < 100)
    {
        play = rand() % COUNT;
        printf("%3d Playing: %s\n",cycle+1,tune[play]);
        frequency[play]++;
        cycle++;
    }

    /* Display frequency list */
    puts("Play Frequency:");
    for(t=0;t<COUNT;t++)
        printf("%s, %d\n",
                tune[t],
                frequency[t]
              );

    return(0);
}

At Line 28, a random number is chosen from 0 to COUNT. The tune is “played” or output at Line 29. The element representing the random tune, play, is incremented in the frequency[] array at Line 30. Line 31 increments the cycle counter.

When the code has run through 100 random tunes, the contents of the frequency[] array are displayed, indicating how many times each tune played:

...
 99 Playing: Lady
100 Playing: Smooth
Play Frequency:
Brandy, 5
Respect, 6
Hey Jude, 5
The Twist, 4
Uptown Funk, 6
Macarena, 2
Killer Queen, 6
Lady, 2
Foolish Games, 2
Call Me, 8
Royals, 3
The Sign, 3
Happy, 7
Billie Jean, 6
My Sharona, 9
Family Affair, 6
Hurts So Good, 3
Smooth, 8
Mack The Knife, 5
No One, 4

In the sample output above, you see that My Sharona played 9 times during the cycle but Lady played only twice. Upon reviewing the full output, I see how several tunes played twice in a row. That’s merely the nature of pseudo random numbers — unless you can track them and prevent them from repeating.

Use the code presented here as a base, or craft your own, to limit a song from playing within 15 songs from itself. For example, if My Sharona is the 3rd tune played, it can play again until after the cycle count reaches 18.

Please try this exercise on your own before you check out my solution.

Leave a Reply