Nb aléatoires sans repetitions
romain chambard
-
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
Bonjour,
je voudrais savoir s il est possible(et je pense que oui) de générer des nombres au hasard sans répétition; par exemple je voudrais rentrer dans un tableau 9 nombres allant de 1 a 9 générés de manière aléatoire sans répétition
merci de votre aide
je voudrais savoir s il est possible(et je pense que oui) de générer des nombres au hasard sans répétition; par exemple je voudrais rentrer dans un tableau 9 nombres allant de 1 a 9 générés de manière aléatoire sans répétition
merci de votre aide
A voir également:
- Nb aléatoires sans repetitions
- Nb si en anglais - Guide
- Nb si couleur - Guide
- Souris t'nb sans fil ne fonctionne pas - Forum souris / Touchpad
- Bisoncam nb pro - Télécharger - Pilotes & Matériel
- Tirage au sort excel aléatoire sans doublon ✓ - Forum Excel
2 réponses
J'avais proposé plusieurs codes dans une discussion similaire en Java :
Nombre aleatoire sans répitition en java
Dans ton cas, c'est ma méthode alea2 qui correspond le mieux à ton problème.
Il est facile de la traduire en C, mais le plus intéressant c'est surement les explications que j'avais mis avant (même si elles ne faisaient pas l'unanimité)
Nombre aleatoire sans répitition en java
Dans ton cas, c'est ma méthode alea2 qui correspond le mieux à ton problème.
Il est facile de la traduire en C, mais le plus intéressant c'est surement les explications que j'avais mis avant (même si elles ne faisaient pas l'unanimité)
KX
Messages postés
16761
Date d'inscription
Statut
Modérateur
Dernière intervention
3 020
Conversion en C de mon code Java :
Sinon une autre solution fonctionnelle et simple consiste à remplir un tableau de la taille voulue avec les nombres croissants par exemple, donc dans ce cas un tableau de 9 cases contenant les chiffres de 1 à 9, puis de mélanger le contenu de ce tableau aléatoirement: il suffit donc de tirer des nombres aléatoires sans se préoccuper des répétitions et d'échanger la 1ère case du tableau avec celle correspondant au nombre tiré une trentaine de fois et voilà, le tableau contient un mélange des chiffres voulus sans répétitions...
@KX ne maitrisant pas le C j'ai compris après coup que ma proposition est assez proche de la tienne, mais elle permet aussi quelques simplifications, je me suis permis de reprendre ton code pour le montrer:
#include "stdlib.h" #include "stdio.h" #include "time.h" // Choix de k valeurs aléatoire entre 0 et n-1 int* alea(int k, int n) { int i,r, temp; int* tab = (int*) malloc(n*sizeof(int)); for (i=0; i<n; i++) tab[i]=i; for (i=0; i<k; i++) { r = rand() % (n-i); temp = tab[r]; tab[r] = tab[0]; tab[0] = temp; } return tab; } int main() { srand(time(NULL)); int i; int* tab = alea(9,9); for (i=0; i<9; i++) printf("%d ",tab[i]); free(tab); system("PAUSE"); return 0; }
J'ai fait une erreur de traduction Java-C, ou plus exactement une erreur de copier-coller, puisque j'avait donné une taille "n" au tableau "tab" (comme pour mon tableau "val") alors qu'il devait avoir une taille "k".
Bien sûr, dans le cas qui nous intéresse on a k==n et ça ne change rien, mais du coup mon erreur affecte aussi ton code, puisque le tableau de retour sera de taille "n" et non de taille "k".
Par contre il y a un problème dans ton code, parce que tu "remets en jeu" les nombres déjà échangés car tu les mets en première case (alors que moi je les mettait en dernière case) du coup la première case peut être à nouveau permutés alors que les dernières cases sont toujours bloquées.
Conséquence : avec ta "simplification", la plupart des cases restent dans l'ordre, on perd l'aléatoire...
Bien sûr, dans le cas qui nous intéresse on a k==n et ça ne change rien, mais du coup mon erreur affecte aussi ton code, puisque le tableau de retour sera de taille "n" et non de taille "k".
Par contre il y a un problème dans ton code, parce que tu "remets en jeu" les nombres déjà échangés car tu les mets en première case (alors que moi je les mettait en dernière case) du coup la première case peut être à nouveau permutés alors que les dernières cases sont toujours bloquées.
Conséquence : avec ta "simplification", la plupart des cases restent dans l'ordre, on perd l'aléatoire...
Ah oui c'est juste mon code n'est pas fonctionnel, je pensais trop au cas précis qui nous concernait pour lequel ce correctif convient, si je ne fait pas d'erreur, mes notions en C n'ayant pas évoluées depuis tout à l'heure!
Ma "simplification" ne faisait que limiter ton code qui est parfait pour son domaine d'application!
Ma "simplification" ne faisait que limiter ton code qui est parfait pour son domaine d'application!
#include "stdlib.h" #include "stdio.h" #include "time.h" int* alea(int k) { int i,r, temp; int* tab = (int*) malloc(k*sizeof(int)); for (i=0; i<k; i++) tab[i]=i; for (i=0; i<k; i++) { r = rand() % (k); temp = tab[r]; tab[r] = tab[0]; tab[0] = temp; } return tab; } int main() { srand(time(NULL)); int i; int* tab = alea(9); for (i=0; i<9; i++) printf("%d ",tab[i]); free(tab); system("PAUSE"); return 0; }
Non, le problème est toujours là, en fait ce que je fais c'est que j'organise un "stock" de valeur au début du tableau, à l'étape i je tire donc aléatoirement un nombre entre les (n-i) valeurs restantes de mon stock, pour le permuter à la fin du stock (à la case n-i-1), puis grâce à l'incrémentation de i revient à diminuer le stock et donc de bloquer la case qui vient d'être permutée.
Mais ton code ne fait pas du tout ça, car tu tires à chaque fois un nombre entre 0 et k-1, ce qui signifie que tu peux permuter plusieurs fois la même case. Certaines cases ne seront donc jamais permutée, et seront toujours à la même place qu'au départ, c'est à dire que tab[i]==i...
Mais ton code ne fait pas du tout ça, car tu tires à chaque fois un nombre entre 0 et k-1, ce qui signifie que tu peux permuter plusieurs fois la même case. Certaines cases ne seront donc jamais permutée, et seront toujours à la même place qu'au départ, c'est à dire que tab[i]==i...
Oui tout à fait, mais c'est tout fait fonctionnel quand même puisqu'en fait il annule son action dans le seul cas où la même valeur sort deux fois de suite, sinon la valeur de la case 0 à changé entre temps! En fait on échange à chaque fois le contenu de la case précédemment tirée avec celui de la nouvelle case tirée au sort... Mais le faire "K" fois peut être un peu juste, il vaut mieux faire K*2 ou K*3 itérations pour être sûr du brassage.
Et quelque part, il n'est pas très grave que certaines cases restent inchangées... ce qui compte c'est qu'il y ait un certain mélange un peu partout, ce qui a pour conséquence de tout mélanger!
Et quelque part, il n'est pas très grave que certaines cases restent inchangées... ce qui compte c'est qu'il y ait un certain mélange un peu partout, ce qui a pour conséquence de tout mélanger!