-3

// What I mean by this is shown by my example:

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

int i;
int a;


for (a = 0;a <10;a ++) {
    i = (rand()%10)+1; // generates a number from 1-10
    printf("%d\n", i);
}

// I would like for the loop to generate a number that gives a number that was not generated before. For example, an output such as:

1,3,6,2,8,9,4,10,5,7

instead of:

3,9,10,3,7,9,2,7,10,1

In other words, I would like no copies.

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
Chris
  • 1
  • 5
    It seems that you are trying to *shuffle* the array (like shuffling a deck of cards). Google "shuffling algorithm". – Robert Lozyniak Jul 21 '18 at 15:20
  • in general, just remember previous numbers in an array and compare, rejecting duplicates. But your special case seems to be you want every number in a specific range exactly once, and that's what @RobertLozyniak already addressed. –  Jul 21 '18 at 15:25
  • See (amongst other SO questions), [Shuffle array in C](https://stackoverflow.com/questions/6127503) and [Is this C implementation of the Fisher-Yates shuffle correct](https://stackoverflow.com/questions/3343797), and links from those pages, including [The Danger of Naivete](http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html) – Jonathan Leffler Jul 22 '18 at 00:12

2 Answers2

2

You obviously don't just want no copies, but you want every number in a given set exactly once. This is, as commented by Robert, similar to shuffling a deck of cards. You don't have "decks" in C, but you can model one as an array:

int deck[] = {1,1,1,1,1,1,1,1,1,1};

This should represent 10 different "cards" (identified by their index in the array), each available one time. Now, just write code that "draws" cards:

int i = 0;  // starting point for searching for the next card to draw
for (int n = 10; n > 0; --n)  // how many cards are left
{
    int skip = rand() % n;  // randomly skip 0 .. n cards
    while (1)
    {
        if (deck[i])             // card still available?
        {
            if (!skip) break;    // none more to skip -> done
            --skip;              // else one less to skip
        }

        if (++i > 9) i = 0;      // advance index, wrapping around to 0
    }
    deck[i] = 0;              // draw the card
    printf("%d\n", i+1);      // and print it out
}

of course, seed the PRNG (e.g. srand(time(0))) first, so you don't get the same sequence every time.

0

The idea shown in the question is to print numbers within a range, without repetition. Here is one way to do that, by putting each value into an array and swapping its elements around.

A variation could be that you don't want to use all the possible numbers, in that case just change PICKED.

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

#define ARRLEN 10
#define PICKED 10

int main(void) { 
    int array[ARRLEN];

    srand((unsigned)time(NULL));        // seed the PRNG

    for(int i = 0; i < ARRLEN; i++) {       // generate the numbers
        array[i] = i + 1;
    }

    for(int i = 0; i < ARRLEN; i++) {       // shuffle the array
        int index = rand() % ARRLEN;
        int temp = array[i];
        array[i] = array[index];        // by randomly swapping
        array[index] = temp;
    }

    for(int i = 0; i < PICKED; i++) {       // output the numbers
        printf("%d ",  array[i]);
    }
    printf("\n");
}

Program output:

9 8 4 5 1 10 7 3 6 2

The library's PRNG is not very random, but for many cases that is not important. If it is, better algorithms are available.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • This code can be adapted to the scenario shown in [The Danger of Naiveté](http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html) with ARRLEN and PICKED both set to 3. It can then be either run repeatedly or modified further to extract most of what's in `main()` into a function `shuffle_once()` that can be called many times from `main()` — leaving `srand()` in the revised `main()`, of course. When run with 60000 iterations, then run through `sort | uniq -c | sort -n`, you get skewed output such as: `8754 321` — `8869 312` — `8966 123` — `11005 231` — `11126 132` — `11280 213`. – Jonathan Leffler Jul 23 '18 at 12:29