开发者

how to create a random 2d array in C with values repeating only twice

开发者 https://www.devze.com 2023-01-23 11:42 出处:网络
im very new to c programming and have done only if/else, loops, arrays, pointers, functions and structs. I would be very glad if anyone could tell me how to create a 2d array which would contain rando

im very new to c programming and have done only if/else, loops, arrays, pointers, functions and structs. I would be very glad if anyone could tell me how to create a 2d array which would contain randomized with time, but would have values that are repeated only twice...

meaning for example:

1 2 3 6
8 7 4 5
7 5 6 3
2 1 4 8

actually i need the array to be 6x6 and so f开发者_JAVA技巧ar i have come to this stage which does not work:

int x,y;
int i,j;

srand (time(NULL));

for ( x=0 ; x<6 ; x++){
    for ( y=0 ; y<6 ; y++) {
        sBoard[x][y] = rand() %36;          /*randomization*/

        for ( i=0 ; i<6 ; i++){  /*trying to create an unique array*/
            for ( j=0 ; j<6 ; j++) {
                if ((sBoard[x][y] == sBoard[i][j])) {
                    x--;
                    y--;
                }
            }
        }
        printf ("%i",sBoard[x][y]);
    }
    printf("\n");
}

======================================================================================= my lecturer asked me to try and use an if function to check whether the value is repeating anywhere else on the matrix... that is why im using an 'if'...i would be very grateful if you could help me... thank you in advance...


The problem is that your if-then block still doesn't guarantee that level of uniqueness. You'd have to have a while-loop to be able to get this to work right. This while loop could theoretically never terminate, and (more likely) would take significantly different amounts of time to execute each time you ran it.

What might be much easier is to populate a 2-d array with all of the values, then shuffle THAT. You can cheat, and treat it as a 1-d array, and it will still work the same way. Here is some pseudo-code:

pointer-to-array pArray;
for i = 0 to 35
    pArray[i] = i
numShuffle = 2;
for s = 1 to numShuffle
    for i = 0 to 35
        swap pArray[i] with pArray[random 0 to 34 - if equal, add 1]

This will guarantee that no duplicates exist, and your code will always take exactly the same amount of time to execute (rather than the while-loop I mentioned above potentially never terminating).

You may be able to set numShuffle to 1 and get favorable results. If you find this to be true, you don't even need that outer loop.


What is the range of the values allowed? Supposing it's not too large, some N, I'd propose the following algorithm:

  • Initialize seen as an array of N int counters, specifying how many time each value was generated.
  • Go over your target 2D array, generate a number num with rand.
    • If seen[num] is 2, re-generate num and try again
    • Otherwise increase seen[num] and place num in its slot in the 2D array

Naturally, seen must be initialized with all zeros.

If the range of numbers is large (say, the whole integer range), I would use a hash table instead of the seen array.


The first thing is that random does not exclude repetition in and of itself - random distribution is just that, random, and no evenly distributed set that means no item would occur again. So I would start (for simplicity's sake) by flattening the 6x6 2d array into a 36x 1d array, and then reorganising it later.

So using a 1d array, you can loop through, and for each position, in a do loop, generate a random number, then you can have an inner for loop that iterates through the existing array from 0 up to the current position, and if the random number is seen at one of those positions, mark a flag to say it's already been seen. That way you can end the do loop with "while(notUnique)".

Ok - show me the code!

int board1d[36];
int pos;
for(pos = 0; pos < 36; pos ++) {
  int newRand;
  int notUnique;
  do {
    int innerPos;
    notUnique = 0;
    newRand = rand() % 36;
    for(innerPos = pos; innerPos > 0 && notUnique==0; innerPos--) {
      notUnique = (newRand == board1d[innerPos]);
    }
  } while(notUnique);
  board1d[pos] = newRand;
}

This does, as mentioned above, potentially mean that if the random generator generates a sequence that repeated, then the loop would take more cycles. There is no guaranteed even distribution in a random set.


I'm a little bit confused about the following: Is the 2d-array allowed (a) to contain a specific value twice as a maximum or (b) should the 2d-array hold each value exactly twice all the time?

(a): Build up a helper array holding all allowed values twice each. Then generate a random number as an index for this helper array to choose one of the numbers in it and store it to the "next" position of your desired 2d-array. Don't forget to remove the chosen value from the helper array.

(b): Initially, you could create an 6x6 array holding all values from 1 to 18 twice each. Then, just shuffle the values around by swapping two values per iteration.

edit: Regarding your own approach and some other solution proposals: I think a try-and-error approach is not the best way to ensure that every value is stored (only) twice. Because, theoretically, it could result in an endless loop. Yes, I know, this is unlikely to happen, but it's a little bit dirty anyway, in my opinion. I'd prefer a solution with deterministic/constant execution time preventing unnecessary operations.

0

精彩评论

暂无评论...
验证码 换一张
取 消