4

this is the part of my code I'm having trouble with. I can't understand why its doing it wrong. I have an array where it stores numbers 0 - 25 which are cases. The numbers are to be randomized and overwritten into the array. Only condition is is that no number can be doulbes, there can only be one of that number. I'm not asking you to do my code but do hint me or point me in the write directions. I am trying to learn :)

The problem lies within the second do loop. I can get the numbers to be randomized, but I get doubles. I have created a loop to check and fix this, but it's not working. The code does run, and doubles do still happen and I can't see why. It looks correct to me. Please look, thank you (:

This is what I have done originally (at the very end is where I am at now):

int check_double = 0;
int i = 0;
int counter = 0;
int array_adder = 0;
int random_number = 0;

int cases[] = {
    1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
    };

float money[] = {
    0.01,1,5,10,25,50,75,100,200,300,400,500,750,1000,5000,10000,25000,50000,750000,100000,200000,300000,400000,500000,750000,1000000
    };

//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
    cases[counter]= rand() % 26;
    counter += 1;
    printf("%d\n", cases[counter]);
}
while (counter <= 25);

//make sure there are no doubles in the array, just 0 - 25 and not a single number repeated twice
do
{
    check_double = 0;

    for (i = 0; i < counter; i++)
    {
        if (cases[counter] == cases[i])
        {
            cases[counter] = rand()% 26;
            check_double == 1;
        }
    }
}

while (check_double != 0);

Currently, what I had achived after that was combing both loops and check for doubles as the array goes. This is what I made, it still has doubles and im not sure why, I only posted the cose with both loops combined:

do
{

cases[counter]= rand() % 26;

if (cases[counter]>=1);

    for(i=0;i<=counter;i++)

    if (cases[counter]==cases[i])
        {
            cases[counter]=rand()% 26;
        }

printf("%d\n",cases[counter]);
counter+=1;
}
Robolisk
  • 1,682
  • 5
  • 22
  • 49
  • [This answer](http://stackoverflow.com/questions/1608181/x/1608585#1608585) to a different question may be helpful to you. – icktoofay Sep 21 '11 at 05:23
  • The normal way to handle that is to load the array with the values 0..25 (or other range) and then shuffle it. There are more and less correct ways of shuffling the array, but you end up with a pure permutation of the guaranteed unique values. – Jonathan Leffler Sep 21 '11 at 07:20

5 Answers5

2

Robsta, you could try the following piece of code, I have run this in Dev-C++, any changes that you require can be made from your side. But, I assure you that this code generates what you intend.

int check_double = 0;
int i = 0;
int counter = 0;

int cases[] = {
    1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
    };
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{

cases[counter]= rand() % 26;

   for(i=0;i<counter;i++)
    if (cases[counter]==cases[i]){
      while (cases[counter]==cases[i])
        {
            cases[counter]=rand()% 26;
        }
      i=0;
    }

printf("%d\t%d\n",counter,cases[counter]);
counter+=1;
}while (counter <= 25);

If you have any clarifications required, I would love to discuss with you.

-Sandip

Sandip Agarwal
  • 1,890
  • 5
  • 28
  • 42
  • So making i=0 again after the inital while loop, that does it? I've been playing with this all night. I'm 100% new to C and new to array, and this random. So this has been quite hard for me. Thank you. – Robolisk Sep 21 '11 at 16:27
  • MY friend. This is EXACLY what I need. Alot of people on this website helped me with it and hinted me, and all gave me diffrent ways. Your way is the way that I wanted and I believe is what user "LaceySnr" wanted or hinted me towards but I couldn't catch it. Thank you. – Robolisk Sep 21 '11 at 16:32
  • 1
    It turns out this way didnt work prefectly. it still gave a double. But, only one double. and it was the very first number. – Robolisk Sep 21 '11 at 19:32
  • Hi, Robsta. I actually put i=0 again to recheck if the new random number generated isn't the same as some other number way below in the array. And this way I reached a solution. If you still are getting a double (even once), its something to be thought of seriously. Could you please provide the set of output that you obtained in that double case (I hope you had written it into a file) if possible. And please take care that you need not put the statement **if (cases[counter]>=1)** as it was in your revised code as it would be a **huge** source of bug. I would love to discuss further on this. – Sandip Agarwal Sep 22 '11 at 05:43
  • Hi, Robsta. The bug was from my side. I am really sorry I didn't take care of that.... You only have to replace **i=0** with **i=-1**. Rest its the same and you get the correct results. This time I crossed checked it. I did that because after i=0 is executed it gets incremented to i=1 because of the loop's increment. So, I made it to i=-1 so that it finally comes to i=0 even after the loop's increment. – Sandip Agarwal Sep 22 '11 at 06:15
  • Hey Sandip, I really apreciate your time and knowledge with helping me. I did the fix taht you did, and put the -1 and it did work. I am very thank full for your help and it makes sense why you did this. I have learned a lot, suprisingly (: Thank you again. Sorry I couldn't get back to you sooner. – Robolisk Sep 22 '11 at 18:13
  • You are welcomed Robsta. Its was my pleasure helping you. Moreover I love solving C/C++ problems. Hope to have more discussions like in future as well. I also have learn't a lot from this. :D – Sandip Agarwal Sep 23 '11 at 04:33
1

You're only ever writing over the last value in the array:

for(i=0;i<counter;i++)
    if (cases[counter]==cases[i])

You need to loop through as you are, then have an inner loop, where you compare all the other entries to the current one.

Even easier would be to do the loop where you set each random number, so when you set cases[3] for example, loop from 0 to 2 and check to see if your new value for 3 clashes, if so, wash - rinse - repeat!

Matt Lacey
  • 8,227
  • 35
  • 58
  • Set each random number? You mean up in my first do loop? and I understand what you mean about that, that makes sense. – Robolisk Sep 21 '11 at 05:29
  • Yeah that's it, pick a number, test to see if it's valid, if not then pick another. That way should also be more efficient than the way you have it now as you won't have to look at the array entries after the one you're examining. – Matt Lacey Sep 21 '11 at 05:31
  • ahhhhhh. I get what your saying. Okay. I'll give it a go and post back my sucesss (: – Robolisk Sep 21 '11 at 05:34
  • Good luck :) Didn't want to be too precise so that you could work it out for yourself! – Matt Lacey Sep 21 '11 at 05:36
  • Of course. I updated my comment. Take a look at the very end, I tried to do what you said/hinted but it didn't work out. Any more clues as to what I'm doing wrong? It's still doing doubles :/ – Robolisk Sep 21 '11 at 05:56
  • You're still only changing it once if you find a double, try using while statement instead of `if (cases[counter]==cases[i])` ;) – Matt Lacey Sep 21 '11 at 06:10
  • but what about the part that's in the if statment? Is that correct? – Robolisk Sep 21 '11 at 06:33
  • Well you still need another loop, to check all the existing values — basically how Mark H has done it is how I was trying to lead you! – Matt Lacey Sep 21 '11 at 06:36
  • I looked at what Mark H has made, and because I'm new to c, it was a little confusing to understand what was going on. I see that he did some sort of swap with a temp variable. I do apreciate all the time you helped me with. – Robolisk Sep 21 '11 at 16:28
1

You have this line of code:

check_double==1;

That doesn't change check_double because it's ==, not =. == compares; it doesn't assign. Change that line to this:

check_double=1;

A helpful compiler (clang in this example) will give you a warning about this:

test.c:5:14: warning: expression result unused [-Wunused-value]
        check_double==1;
        ~~~~~~~~~~~~^ ~
icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • Thank you. That I didn't notice D: But I apreciate you telling me that, although. It still didn't fix my problem :/ – Robolisk Sep 21 '11 at 05:26
1

You can't check for duplicates with a single loop. You need to at least compare every possible pair of elements to be able to see if there's a duplicate. I'm guessing you forgot to loop over counter somewhere inside the second do...while?

Note that your method is not guaranteed to terminate. (Very, very likely but not certain.) Why don't you simply shuffle the cases array? Shuffling is simple but tricky; see Fisher-Yates (or Knuth) Shuffle for a simple algorithm.

aib
  • 45,516
  • 10
  • 73
  • 79
  • Hey, thanks. I'll take a look at that. I never knew of such a way. What do you mean add another loop? – Robolisk Sep 21 '11 at 05:27
  • Right now you're checking if any element is equal to `cases[26]` which doesn't even exist. I think you meant something along the lines of `for i=0 to 26 .. for j=i+1 to 26 .. if cases[i] == cases[j] then duplicate; regenerate and recheck`? If that's the case you missed a loop. – aib Sep 21 '11 at 05:53
  • BTW, you *can* check for duplicates with a single loop (using O(N) memory along with the O(N) running time), but that's even more complicated. I'd simply shuffle the array once and be done with it. – aib Sep 21 '11 at 05:54
  • The thing is, if I were to do a shuffle I'd have to explain how to do one or how I achived one/learned it. So I'm going to read more into that shuffle, and if it works, then perfect (: – Robolisk Sep 21 '11 at 05:58
1

If you are asking how to randomly sequence the number 1-25 then you could do something like this. This is a very brute-force way of generating the sequence, but it does work and might give you a starting point for something more optimized.

#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <conio.h>

const int LastNumber = 25;

bool HasEmpty(int available[LastNumber][2])
{
    bool result = false;
    for(int i = 0; i < LastNumber; i++)
    {
        if (available[i][1] == 0)
        {
            result = true;
            break;
        }
    }

    return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
    int available[LastNumber][2];
    int newSequence[LastNumber];

    srand((unsigned int)time(NULL));

    for(int i = 0; i < LastNumber; i++)
    {
        available[i][0]=i;
        available[i][1]=0;
    }

    int usedIndex = 0;

    while (HasEmpty(available))
    {
         int temp = rand() % (LastNumber + 1);
         if (available[temp][1] == 0)
         {
             newSequence[usedIndex++] = available[temp][0];
             available[temp][1] = 1;
         }
    }   

    for(int i = 0; i < LastNumber; i++)
    {
        printf("%d\n",newSequence[i]);
    }

    getch();

    return 0;
}
Mark
  • 595
  • 5
  • 13
  • That is defeintly a new way to look at it and I never thought of it. I'm going to take a closer look into this. Thank you. – Robolisk Sep 21 '11 at 06:00