2010-02-28 9 views
7

Je suis occupé en C# avec codage d'un tableau. Je peux le remplir avec des générateurs aléatoires, mais est maintenant ma question comment puis-je faire cela, mais pour que je puisse vérifier si la valeur est déjà dans le tableau et le cas échéant générer une nouvelle valeurGénérateur de nombres aléatoires en C# - valeurs uniques

Extra info:
Valeur max : 100
Nombre d'éléments: 100

IMPORTANT dE TRAVAIL PLZ COMPLEMENTAIRES SUR mON iDÉE

mon idée

public void FillArray(int[] A, int Range) 
{ 
    for (int I = 0; I < A.Length; I++) 
    { 
     A[I] = ValidNumber(T, I, Range); 
    } 
} /* Fill Array */ 

Mise en œuvre de la sélection sorte

public void SelectionSort(int[] A) 
{ 
    int K, X; 
    for (int I = 0; I < A.Length - 1; I++) 
    { 
     K = I; 
     X = A[K]; 
     for (int J = I + 1; J < A.Length; J++) 
     { 
      if (A[J] < X) 
      { 
       K = J; 
       X = A[K]; 
      } 
     } 
     A[K] = A[I]; 
     A[I] = X; 
    } 
} /* Selection sort */ 

Ce ne sont que quelques idées maintenant je veux savoir comment je peux le réparer si je peux regarder avec sorte de sélection s'il y a là ALLREAD (FillArray) qui est même le cas échéant remplacer avec une nouvelle valeur aléatoire. Et donc je veux créer un tableau aléatoire avec ints - de 1 à 100 dans un ordre aléatoire

+1

Odeur comme des devoirs, surtout avec les commentaires ci-dessous les (valides, bonnes) suggestions avec un squelette qui semble faire partie de la tâche: "Commencez avec ce code" –

+0

oui c'est en effet une partie de devoirs je ne sais pas va mentir à ce sujet je suis coincé dans une partie et je veux des conseils/commentaires qui ne sont pas mauvais je suppose – ShallowHeart

+1

indentation du code correct et de meilleurs noms de variables aiderait les gens à comprendre votre code et par conséquent vous donner de meilleures solutions. – CesarGon

Répondre

6

Ce qui suit va générer un tableau avec les numéros 1-100 dans un ordre aléatoire.

Random rnd = new Random(); 
    var randomNumbers = Enumerable.Range(1, 100).OrderBy(i => rnd.Next()).ToArray(); 
+0

Vous devez fournir une graine à 'Random()', par ex. 'new Random (DateTime.Now.Millisecond)' – AxelEckenberger

+8

Le constructeur vide sur Random le fait par défaut (Enviroment.TickCount) –

+10

@Obalix: Non, vous ne devriez pas. Vous ne devez fournir une graine que si vous voulez pouvoir redonner la même graine ** plus tard. Sinon, comptez sur l'ensemencement par défaut. –

2

Voici une implémentation naïve:

int[] values = new int[100]; 
Random random = new Random(); 
for(int i = 0; i < values.Length; i++) 
{ 
    int v; 
    do 
    { 
     v = random.Next(100) + 1; 
    } while (Array.IndexOf(values, v) != -1) 
    values[i] = v; 
} 

Mais il serait assez inefficace, surtout à la fin du tableau ...

Une meilleure solution serait de considérer que, depuis vous voulez 100 valeurs distinctes de 1 à 100 dans un ordre aléatoire, votre tableau contiendra éventuellement toutes les valeurs possibles de 1 à 100. Il vous suffit donc de générer une séquence de ces valeurs et de la "mélanger":

int[] values = Enumerable.Range(1, 100).ToArray(); 
Random random = new Random(); 
for(int i = values.Length - 1; i > 0; i--) 
{ 
    int j = random.Next(i + 1); 
    int tmp = values[i]; 
    values[i] = values[j]; 
    values[j] = tmp; 
} 

EDIT: une meilleure approche, qui devrait fonctionner pour les cas moins spécifiques:

T[] RandomCombinationWithNoRepeat<T>(IEnumerable<T> itemsToPickFrom, int numberOfItemsToPick) 
{ 
    // Copy original items to pick from, because we need to modify it 
    List<T> itemsCopy = new List<T>(itemsToPickFrom); 
    T[] array = new T[numberOfItemsToPick]; 
    Random random = new Random(); 
    for(int i = 0; i < numberOfItemsToPick; i++) 
    { 
     // Pick item and remove it from list 
     int index = random.Next(itemsCopy.Count); 
     array[i] = itemsCopy[index]; 
     itemsCopy.RemoveAt(index); 
    } 
    return array; 
} 

Dans votre cas, vous utiliserez comme ça:

int[] result = RandomCombinationWithNoRepeat(Enumerable.Range(1, 100), 100); 
+0

je suis plus à la recherche d'un oop solution \t est été plus penser à une programmation POO quelque chose comme ce public void [code] FillArray (int [] A, plage int) {for (int i = 0; I < A.Length; I ++ A [I] = ValidNumber (T, I, Range)} [/ code] Après cette petite idée, je suis coincé après tout, je suis également le codage très strict je garde l'entrée, le traitement et sortie dans différentes classes – ShallowHeart

+0

Je ne pense pas que la 'List ' contient une propriété 'Length', vous voulez probablement' Count' –

+0

@PhilippeLavoie, oui, vous avez raison ... Je l'ai corrigé, merci! –

5

D'après votre description Je prends que vous avez besoin d'un tableau de 100 nombres entiers avec des valeurs de 1 à 100 et pas de nombres en double. Si les nombres sont des entiers, vous n'avez pas besoin de générer des nombres aléatoires, car tous les nombres possibles sont dans le tableau. Par conséquent, seul l'ordre ou les nombres peuvent être randomisés. En utilisant Linq et l'approche de Jesper Palm - avec Thomas Levesque, la déclaration suivante vous donnera le tableau dont vous avez besoin.

Random rnd = new Random(); 
var randomNumbers = Enumerable.Range(1, 100) 
           .Select(x => new { val = x, order = rnd.Next() }) 
           .OrderBy(i => i.order) 
           .Select(x => x.val) 
           .ToArray(); 

La méthode est même assez rapide, certainement plus efficace que toute comparaison.

Pour expliquer ce qui précède à l'affiche originale, voir le commentaire ci-dessous:

  • Enumerable.Range(1, 100) crée une gamme de nombres entiers commençant à 1 et se terminant à 100.
  • .Select(x => new { val = x, order = rnd.Next() }) crée un nouvel objet temporaire contenant la valeur et la position de la commande, qui est déterminée par un nombre aléatoire.
  • .OrderBy(i => i.order) trie les objets temporaires par sa position d'ordre.
  • .Select(x => x.val) sélectionne la valeur de l'objet temporaire, convertissant ainsi en int.
  • .ToArray() retourne le tout à un tableau à nouveau.

La syntaxe utilisée est LINQ, disponible dans .NET 3.5. Avec les anciennes versions, vous devez l'implémenter vous-même, ce qui est beaucoup plus compliqué et plus long.

Après le commentaire de Eric: Si shuffeling requried vous pouvez faire le code comme suit

var list = myInputList; 
var result = list.Select(x => new { val = x, order = rnd.Next() }) 
       .OrderBy(i => i.order) 
       .Select(x => x.val) 
       .ToArray(); 
+0

thnx vous tous pour la réponse mais pouvez s'il vous plaît regarder mon idée Btw ho w ajoutez-vous du code dans cette case grise? Ouais, je suis un débutant ici. Aussi, je tiens à noter que je suis un débutant à C# seulement quelques mois d'expérience. Et je ne sais même pas ce que quelque chose que vous présentez ici même mee comme enumerable.range qui doit être la gamme. Commander par doit être commander. Mais je suppose que le code va ordonner tous les nombres dans le tableau ce qui n'est pas le concept que je ne veux pas atteindre. Je veux atteindre juste un tableau aléatoire avec 100 éléments avec des nombres entre 1 et 100 dans un ordre aléatoire. – ShallowHeart

+0

@ShallowHeart, je pense que vous manquez le point. Le code prend les nombres de 1 à 100 et les "trie" dans un * ordre déterminé au hasard *. C'est une technique standard de brassage. –

+0

@Obalix Votre réponse m'a permis de gagner beaucoup de temps. Pouvez-vous me dire ce que je dois faire si je veux obtenir un tableau de disons 30 chiffres où la portée maximale change? Ce que j'ai fait était de générer le tableau de nombres aléatoires pour la gamme complète en utilisant votre extrait et stocker les 30 premiers éléments requis dans mon tableau. Comment puis-je modifier ce code pour incorporer même cela pour réduire le temps de bouclage. – Jerin

0

de ce que j'ai compris. Vous avez besoin d'une collection d'entiers avec des nombres aléatoires. Je suppose qu'utiliser int array ou List of int n'a pas d'importance. Voici une approche complète simple que vous avez décrite.
using System; using System.Collections.Generic; using System.Text;

namespace FillRandom { class Program { static void Main(string[] args) { int minValue = 1; int maxValue = 100; //create a list of int with capacity set as 100 List array = new List(100);

 FillArray(array, minValue, maxValue, array.Capacity); 

     //print out all values in the array 
     foreach (int i in array) 
     { 
      Console.WriteLine(i); 
     } 
    } 

    private static void FillArray(List<int> array, int minValue, int maxValue, int capacity) 
    { 
     int count = 0; 
     while (array.Count != capacity - 1) 
     { 
      Random rnd = new Random(); 
      int value = rnd.Next(minValue, maxValue); 
      if (!array.Contains(value)) 
      { 
       array.Add(value); 
      } 
      count++; 
     } 
     //print out the number of times the looping occurs 
     Console.WriteLine("count: "+count); 
    }   
} 

}

Vous pouvez créer un projet de console et l'essayer.

+0

Eric a tout à fait raison: c'est vraiment une mauvaise idée et j'ai essayé de l'imprimer en utilisant "count". ;) Quoi qu'il en soit, une découverte intéressante est qu'il rend plus difficile le remplissage du tableau si un nouvel objet aléatoire a été créé à chaque fois (environ 100k à 200k boucles) mais en utilisant le même objet, il a fallu environ 500 fois. – Blithe

30

Comment puis-je faire cela, mais pour que je puisse vérifier si la valeur est déjà dans le tableau et le cas échéant générer une nouvelle valeur

Vous ne faites pas cela, jamais, parce que est une très mauvaise idée.

Pour illustrer pourquoi il est une très mauvaise idée, envisager une autre version du même problème: trier un million de numéros dans un ordre aléatoire par le procédé suivant:

  1. Choisissez un numéro un à un million.
  2. Vérifiez pour voir si elle est déjà dans la liste.
  3. Si c'est le cas, retournez à l'étape 1
  4. Sinon, ajoutez le numéro à la liste.
  5. La liste contient-elle un million d'éléments? Si oui, vous avez terminé. Si ce n'est pas le cas, retournez à l'étape 1.

Cela fonctionne clairement. Est-ce que c'est une bonne idée? Supposons que vous avez presque fini. La liste contient 999999 articles. Le seul élément manquant est 857313. Que faites-vous? Vous choisissez un nombre aléatoire, par exemple, 12. Maintenant, vous vérifiez les 999999 éléments de la liste pour voir si l'un d'entre eux sont 12. 12 aurait pu être l'un des premiers numéros que vous avez choisi, il peut donc être rapide pour le trouver. Ou il pourrait être l'un des derniers, donc cela prendra beaucoup de temps. En moyenne, il faudra 500 000 vérifications pour voir si 12 est sur la liste. Et c'est le cas, car il n'y a qu'un seul nombre manquant dans la liste.

12 ne fonctionne pas. Revenez au début. Choisissez un autre nombre aléatoire, disons, 53259. Est-ce que c'est sur la liste? Encore un demi-million de chèques. Continuez à le faire jusqu'à ce que vous générez 857313, ce qui arrive un million d'essais.Donc, en moyenne, mettre le dernier élément de la liste prend 500000 x 1000000 = cinq cent milliards de comparaisons. Cela pourrait prendre plus de temps. Cela pourrait prendre plusieurs milliers de milliards de comparaisons. Ou vous pourriez avoir de la chance et il en faut un. Mais en moyenne, un demi-billion de comparaisons.

Ceci est un terrible façon de produire un ordre aléatoire d'une liste.

Il existe deux méthodes pour effectuer un classement aléatoire d'une liste.

(1) Faire un appareil qui peut trier une liste en fonction d'une commande. Fournir un stable en fonction d'une graine aléatoire.

Notez que vous devriez pas produire un ordre aléatoire en faisant une méthode qui renvoie des résultats aléatoires lorsqu'on lui demande "est plus grand que B?" C'est un ordre instable; de nombreux algorithmes de tri sont basés sur un ordre de tri stable et vont dans des boucles infinies ou ont d'autres mauvais comportements quand on leur donne un ordre de tri instable.

Cet algorithme est O (n lg n) et a la bonne propriété d'écrire très facilement des parties standard, comme d'autres réponses l'indiquent. Il est également extrêmement rapide pour les petites listes dans les implémentations typiques.

(2) Choisissez un article par index à partir d'une liste source au hasard, en supprimant de la liste des sources que vous allez, et en le mettant sur la liste de destination. Ce dernier est connu sous le nom de Knuth Shuffle ou Fischer-Yates Shuffle, et il s'agit d'un algorithme très rapide. Vous pouvez le faire "en place", en faisant muter un tableau existant dans l'ordre mélangé, ou en créant une nouvelle liste. Il a aussi la belle propriété que vous pouvez "payer pour jouer", mélanger le "haut" de la liste que vous en avez besoin. Si vous avez un million d'objets à mélanger mais que vous n'avez besoin que des cent premiers, vous pouvez simplement définir l'ordre de tri pour la première centaine et l'appeler bien.

+1

Je pense que le deuxième conseil est exceptionnel. –

+0

bonne réponse, c'est une bonne approche car cette question se rapporte à un devoir et vous ne dites pas simplement copier ceci et vous avez terminé +1 –

+0

J'utilise la deuxième méthode en ce moment et c'est merveilleux. Bonne réponse, +1. – Abluescarab

Questions connexes