Random() génére un nombre répété

Résolu/Fermé
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014 - 25 févr. 2014 à 16:46
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014 - 26 févr. 2014 à 20:26
Bonjour à tous,

j'ai un programme en java dont une partie doit générer des nombres aléatoires compris entre (1 à 4 ) avec la fonction Random, et je veux que chaque nombre soit répété n fois.
par Ex :
1 répété 8 fois
2 répété 15 fois
3 répété 20 fois
...

J'ai besoin de votre aiiiiiiiiiiiiiiiiiiiiiiiiide!!,

Merci ^^

3 réponses

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
Modifié par KX le 25/02/2014 à 18:27
Si j'ai bien compris le résultat est fixé :

1 répété 8 fois
2 répété 15 fois
3 répété 20 fois
...

Or avec un random simple tu vas avoir en moyenne autant de répétition pour chaque valeur. Donc dans une grille 100x100 ça fait environ 2500 de chaque. On est loin de 8, 15 et 20. Ou alors j'ai mal compris...
1
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014
25 févr. 2014 à 19:29
j'ai juste donner des exemple avec ces chiffres, ce que je veux comment je peux fixer pour chaque nombre ( de 1 à 4) le nombre de sa répétition ???
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
25 févr. 2014 à 19:59
Le plus simple c'est de partir d'un tableau rempli avec le nombre de valeurs fixées (sans aléatoire), puis tu mélanges le tableau.

Exemple :

public static Integer[] fill(int...nb)
{
    int sz = 0;
    for (int n : nb)
        sz+=n;
    
    Integer[] tab = new Integer[sz];
    
    for (int i=0, j=0; i<nb.length; i++)
        Arrays.fill(tab, j, j+=nb[i], i+1);
    
    return tab;
} 

public static void shuffle(Integer...tab)
{
    List<Integer> list = Arrays.asList(tab);
    Collections.shuffle(list);
    list.toArray(tab);
}

public static void main(String[] args)
{        
    Integer[] tab = fill(1,2,3,4);
    System.out.println(Arrays.toString(tab)); // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
    shuffle(tab);
    System.out.println(Arrays.toString(tab)); // [4, 1, 3, 4, 3, 4, 3, 2, 2, 4]
}
0
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014
25 févr. 2014 à 21:03
premièrement je vous remercie beaucoup pour l'intérêt que vous portez à mon problème

c'est une grille remplie d'états (1,2,3,4),dans mon programme chaque état est représenté et affiché par une couleur (comme un damier) le seul problème que j'ai comment je peux l'lorsque je distribue les états sur la grille de fixer le nombre de chaque états, (sachant combien j'ai de 1 et de 2 .. je dois les distribuer d'une façon aléatoire)
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
25 févr. 2014 à 21:24
Une fois que tu as mélangé tes valeurs dans un tableau, il est facile de passer à une grille, il suffit de réordonner les case tab[n*i+j] en mat[i][j]
0
walidovich_85 Messages postés 608 Date d'inscription mardi 12 janvier 2010 Statut Membre Dernière intervention 25 octobre 2015 73
25 févr. 2014 à 16:59
bonjour,

pouvez vous nous partager votre ebauche du programme?
0
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014
25 févr. 2014 à 17:03
voici la partie dans la quelle je doit indiquer le nombre de fois que chaque nombre doit se répéter, mais je sais pas comment ???

Random r = new Random();

public void init(int [][]t){

for(i=0;i<=99;i++){
for(j=0;j<=99;j++){

t[i][j]=r.nextInt(4);
}
}
}
0
walidovich_85 Messages postés 608 Date d'inscription mardi 12 janvier 2010 Statut Membre Dernière intervention 25 octobre 2015 73
25 févr. 2014 à 22:11
Bonsoir tt le monde,

J'ai procédé ainsi pour remplir la grille:

Générer un nombre aléatoire entre 1 et 4;
Contrôler si le nombre de répétition est atteint pour le nombre généré.
Affecter le nombre correcte à la case en itération.

Voila le code:

import java.util.Random;

public class Main1
{
    // des variable de controle
    static int     limit_1 = 15, limit_2 = 20, limit_3 = 30, limit_4 = 35;
    static int     nbr_1, nbr_2, nbr_3, nbr_4;
    static int[][] grille  = new int[10][10];
    static Random  rand    = new Random();
    static int     r;

    public static void main(String args[])
    {
	for (int i = 0; i < 10; i++)
	{
	    for (int j = 0; j < 10; j++)
	    {
		// Controle de l'atteinte de limite
		boolean limit = true;
		while (limit)
		{
		    // générer le nombre aléatoire avec Random
		    r = genererNbr();
		    limit = controlLimit(r, limit);
		}
		grille[i][j] = r;
	    }
	}
	int control_1 = 0;
	int control_2 = 0;
	int control_3 = 0;
	int control_4 = 0;

	// Affichage de la grille

	for (int i = 0; i < 10; i++)
	{
	    for (int j = 0; j < 10; j++)
	    {
		// Compteur de répétition
		if (grille[i][j] == 1)
		    control_1++;
		else if (grille[i][j] == 2)
		    control_2++;
		else if (grille[i][j] == 3)
		    control_3++;
		else if (grille[i][j] == 4)
		    control_4++;

		System.out.print(grille[i][j] + " ");
	    }
	    System.out.println();
	}
	System.out.println();

	// Vérification de nombre de répétition

	System.out.println("Nombre de 1: " + control_1);
	System.out.println("Nombre de 2: " + control_2);
	System.out.println("Nombre de 3: " + control_3);
	System.out.println("Nombre de 4: " + control_4);
    }
    static int genererNbr()
    {
	r = rand.nextInt(4) + 1;
	return r;
    }
    static boolean controlLimit(int nbr, boolean limit)
    {
	switch (nbr)
	{
	    case 1:
		if (nbr_1 < limit_1)
		{
		    nbr_1++;
		    limit = false;
		} else
		    limit = true;
		break;
	    case 2:
		if (nbr_2 < limit_2)
		{
		    nbr_2++;
		    limit = false;
		} else
		    limit = true;
		break;
	    case 3:
		if (nbr_3 < limit_3)
		{
		    nbr_3++;
		    limit = false;
		} else
		    limit = true;
		break;
	    case 4:
		if (nbr_4 < limit_4)
		{
		    nbr_4++;
		    limit = false;
		} else
		    limit = true;
		break;
	}
	return limit;
    }
}


et voila un exemple de résultat:

1 4 2 2 4 1 4 4 1 4 
2 2 4 1 3 3 2 2 2 1 
3 2 4 3 3 3 4 3 1 4 
1 2 4 3 4 2 1 3 4 3 
2 3 3 2 2 2 3 3 3 1 
2 3 2 4 2 2 2 3 4 2 
4 1 1 3 4 4 3 1 4 3 
1 3 1 4 3 1 3 3 3 3 
4 4 4 3 3 4 4 4 4 4 
4 4 3 3 4 4 4 4 4 4 

Nombre de 1: 15
Nombre de 2: 20
Nombre de 3: 30
Nombre de 4: 35


Je pense que c'est une méthode directe mais compliquée et elle peut être encore optimisée, car après l'atteinte de la limite pour un certain nombre, ce nombre peut etre encore généré avec la fonction Random; résultat: des boucles inutiles.

PS: si ces nombre sont piqués aléatoirement d'une liste, on peut illiminer une valeur quand on atteint sa limite de répétition, en résultat, éviter des boucles initules.

Bonne chance
0
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014
25 févr. 2014 à 22:43
merciiiiiiiiiiiiiiiiiiiiiiiiiiiii bien walidovich_85 je vais essayer d'optimiser mon code mais vos idées m'ont beaucoup aider.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
25 févr. 2014 à 22:48
"Contrôler si le nombre de répétition est atteint pour le nombre généré."
Cela a un inconvénient que l'on voit bien sur ton exemple, c'est que dès qu'une valeur a été totalement placée, les autres s'accumulent sur la fin, du coup la probabilité de trouver plusieurs 4 à la fin est beaucoup plus grande.

On pourrait mathématiquement améliorer le résultat en biaisant l'aléatoire, pour l'instant tu as 25% de chance d'avoir chaque valeur au tirage puisque tu fais un rand.nextInt(4) + 1, si on veux que les valeurs les moins fréquentes ne se retrouvent pas trop vite épuisées, il faut qu'on les tire moins souvent, proportionnellement à leurs représentations finales.

static int limit_t = limit_1 + limit_2 + limit_3 + limit_4;
static double prop_1 = ((double) limit1)/limit_t;
static double prop_2 = ((double) limit2)/limit_t + prop_1;
static double prop_3 = ((double) limit3)/limit_t + prop_2;
//static double prop_4 = ((double) limit4)/limit_t+ prop_3; // == 1.0

static int genererNbr()
{
    double d = rand.nextDouble();
    if (d<prop_1)
        return 1;
    if (d<prop_2)
        return 2;
    if (d<prop_3)
        return 3;
    return 4;
}

Personnellement, je préfère ma méthode (remplir tout le tableau d'abord puis le mélanger), c'est mathématiquement correct et pas vraiment plus compliqué à mettre en place...
0
walidovich_85 Messages postés 608 Date d'inscription mardi 12 janvier 2010 Statut Membre Dernière intervention 25 octobre 2015 73
Modifié par walidovich_85 le 25/02/2014 à 23:00
Oui, vous avez raison, j'ai pa pu donner assez de temps pour ça à cause du match en champions league :D
0
yasamira Messages postés 15 Date d'inscription mardi 25 février 2014 Statut Membre Dernière intervention 5 juin 2014
25 févr. 2014 à 23:09
Avant de remplir tout le tableau il faut un nombre exacte pour chaque état et c'est ça effet mon problème avec la fonction Random() il faut que le 1 er nombre qu'elle me génère se répète n fois et le 2eme m fois ainsi de suite.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
25 févr. 2014 à 23:11
On a bien compris ta question... à toi de comprendre nos réponses maintenant !
0