Member Avatar for cnet1989

I'm making a program that reads in data from a file into 2 different arrays (one is an int array and another is a char array). And they are parallel. These are songs and song types (hip hop, jazz...etc). I want to print the songs as a playlist then I want to be able to randomize the playlist. To do this I want to make two more parallel arrays, one that randomizes the song name index and the other that consists of true and false values so that a song isn't played more than once that are also parallel to the other first two. But I DON'T want to print the same song more than once. How can I accomplish this (not repeating a song)?

Recommended Answers

All 13 Replies

So it sounds like this is data that gets paired together. So you have something like this:

1 R
2 B
3 F
4 W

where 1, 2, 3, 4 are song numbers. And R, B, F, W are letters representing song type? And you want to randomize the order of the numbers, but you want the same letter to still go with the same number, like this?

2 B
4 W
1 R
3 F

You're worried that if you randomize each array they'll be randomized differently, like this (i.e. numbers are no longer paired with correct letter)?

2 F
4 R
1 B
3 W

Is that the dilemma? You want the first results above, but you are getting the second results above?

Member Avatar for cnet1989

actually the arrays are paired together (Because they are parallel and share the same index)...i just want to randomize them so that they are not repeated. I'm using rand () % 4 (for four songs)

Just read your post a little more closely (and I see you just posted again too). I think I get it a little bit better now, but I'm not sure. You have four songs:

1
2
3
4

You want to play these four songs in random order, but you want to make sure every song is played before any repeats, as in this is a good song order:

3
1
2
4

and this is not

3
4
1
3

because song 3 is played twice before song 2 is ever played? So the question is: How do you randomize the order of the array and make sure that each number in the array occurs exactly once? Is that right?

Member Avatar for cnet1989

Yes

Well, you're working with arrays of 4 elements, so you are really interested in randomizing the array indexes that go along with those arrays. So you want to create random numbers from 0 to 3 and have them occur exactly one.

You are using:

rand () % 4

which is a good way to generate a random integer from 0 to 3, so keep that. The problem is in making sure random numbers don't repeat themselves. Here is one way to do it. I'm not sure if it is the most efficient method, but it's fairly easy to code:

Create a boolean array of 4 elements (same number of elements as the number of songs that there are). This array represents which numbers have ALREADY been picked by the RNG. Initialize the entire array to false (no numbers have been picked yet).

Produce an index randomly from that RNG from 0 to 3. Check this boolean array to see whether the index just generated has already been picked. If it HAS NOT been picked already, keep the index, then flag the boolean array for that index as true (representing that this index has now been picked). If it HAS already been picked, throw that randomly generated index away and pick another one using the RNG. Check again, see if it's been picked. Keep generating until you find an index that hasn't been picked yet. Keep that index, flag it as having been picked already.

Repeat the above paragraph four times, until all possible indexes have been picked. There will be no repeats.

Member Avatar for cnet1989

you mean something like

int randomNumber,
    numsongs = <number of songs>,
    songArray[numsongs], 
    randomNumber;

bool truefalsearray[numsongs];

for (int i = 0; i < numsongs; i++)
{

truefalsearray[i] = false;
} 

for (int i = 0; i < numsongs; i++)
{


if ( !truefalsearray[randomNumber] )
{
 <pass to function that prints song> (songArray[randomNumber] );
 truefalsearray[randomNumber] = true; // change to true so it is not picked again.
randomNumber =rand () % numsongs
} // if

else
{
while (truefalsearray[randomNumber] )
randomNumber =rand () % numsongs;
} // else

} // for

...Question... is it okay to have that rand function in the if statement because technically a random number was generated in the for loop prior to the second one....and also...I want to thank you for all of your help!

for (int i = 0; i < numsongs; i++)
{
     if ( !truefalsearray[randomNumber] )
     {
          <pass to function that prints song> (songArray[randomNumber] );
          truefalsearray[randomNumber] = true; // change to true so it is not picked again.
          randomNumber =rand () % numsongs
      } // if
      else
      {
           while (truefalsearray[randomNumber] )
                randomNumber = rand () % numsongs;
      } // else
} // for

Close. I think you have the right idea. However, in line 3, you are using randomNumber as an array index. The first time through the for-loop, randomNumber has not been initialized. Don't use randomNumber as an array index until it's been generated by the random number generator or you're likely to have a segmentation fault (randomNumber may be something other than 0, 1, 2, or 3. You have no way of knowing before you assign it top some value). So that should give you an idea of where to generate randomNumber. There is more than one way of doing it. You need to generate AT LEAST one random number for every trip through the for-loop. You also need to make a call to the function that displays the song EXACTLY ONCE every time you go through the for-loop. So design your while loop and/or if statements according to the two facts above. You need to make this work if the random number generator never ever produces a duplicate, and you need it to work if it produces 0 500 times in a row. You have no idea what it is going to produce, so it must work for all contingencies.

I would consider renaming your boolean array to something more descriptive like numberAlreadyTaken. That way someone who hasn't read the prior posts (as well as you and I, who have) have an idea of what is being done and why. You added a comment to explain what you were doing, so that's good, but well-named variables are good in addition and will help you keep track of what you are doing and why.

You have a good start.

Member Avatar for cnet1989

are you saying rand () % 4 would generate 0, 1, 2, or 3...and even other numbers???

are you saying rand () % 4 would generate 0, 1, 2, or 3...and even other numbers???

No, rand () % 4 will produce 0, 1, 2, or 3 only. I am saying that, unless I missed something, you use randomNum in your code BEFORE you execute this statement:

randomNum = rand () % 4;

After you call the above line, randomNum will contain 0, 1, 2, or 3, so no segmentation fault worries. I am saying this. When you declare randomNum to be an integer, the compiler picks some address in memory for randomNum to store its value. You have absolutely no control over what address is picked and you have no idea what value was stored in that address BEFORE your program was even started. Let's say, for sake of argument, that that value was 10 before your program started. When you hit line 3 in the code above, randomNum will still be equal to 10 since you never changed it. That's a problem because you only defined your array up through index 3 and you are telling the compiler to check what is stored at index 10. That was my point. Solution? Make sure you generate a random number from 0 to 3 and store it in randomNum BEFORE you use randomNum as an array index.

Member Avatar for cnet1989

it's interesting, yes, but, it's also very confusing to me, thanks anyway. ...

The post linked above is a more complex, but probably much more efficient algorithm than the one I suggested (I haven't analyzed it, but I assume it is). There's a tradeoff: efficiency versus ease of coding. Efficiency would be very important for a record collection of thousands of songs. The method I suggested in this thread could get pretty slow in that case. However, you are talking about four songs. With that few songs, you aren't going to notice a slowdown.

Member Avatar for cnet1989

I'm a beginner...it's actually about 20 songs but...I'm not ready for the really complex stuff yet. I mean, I have to crawl before I can walk

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.