Comment puis-je générer une liste de n nombres aléatoires en Ruby?
C'est ce que j'ai à ce jour:
myArray.map!{ rand(max) }
De toute évidence, cependant, parfois, les numéros de la liste ne sont pas uniques. Comment puis-je m'assurer que ma liste ne contient que des numéros uniques sans avoir à créer un plus grand liste à partir de laquelle j'ai ensuite il suffit de choisir les n nombres uniques?
Edit:
J'aimerais vraiment voir ce fait w/o loop - si possible.
- Pour info, ma réponse montre un modèle qui fonctionne sans boucle
Vous devez vous connecter pour publier un commentaire.
Ce utilise Set:
randoms
sera moins aléatoire querand(max)
depuis que vous êtes tout simplement de jeter les numéros "vous n'aimez pas".(0..50).to_a
peut être remplacé par n'importe quel tableau.0 est "minvalue", 50 "valeur max"
x est "combien de valeurs de i want out"
bien sûr, il est impossible de x pour être autorisés à être plus que max-min 🙂
Dans l'expansion de la façon dont cela fonctionne
Notes de bas de page:
Il est intéressant de mentionner qu'à l'époque, cette question a été à l'origine de réponse, septembre 2008, que
Array#shuffle
sont pas disponibles ou ne sont pas déjà connues de moi, d'où le rapprochement enArray#tri
Et il y a un barrage de suggestions de modifications à ce résultat.
Donc:
Peut être mieux, et de plus courte durée exprimée sur moderne ruby implémentations utilisant
En outre,
Peut être plus évidemment écrite avec
Array#prendre
comme:Ainsi, la façon la plus simple pour produire une séquence de nombres aléatoires sur un moderne ruby est:
.shuffle
)n.times.map { rand(lower_limit..upper_limit) }
Juste pour vous donner une idée sur la vitesse, j'ai couru quatre versions de ce:
Ils sont tous rapidement à de très petites échelles, donc je leur ai demandé de créer une liste de 1 000 000 de numéros. Voici les temps, en secondes:
Et non, ce dernier n'est pas une faute de frappe. Donc, si vous vous souciez de la vitesse, et c'est OK pour les nombres entiers de 0 à quoi que ce soit alors mon code exact était:
(0..10).to_a.sort{ Random.rand() }
sur tryruby.org/levels/1/challenges/0 me donne d'entrée == sortie. Afin de vous VRAIMENT besoin que de 0,5, ou le aléatoire lui-même ne fait riensort
. J'ai effectivement utilisé sort_by, comme je l'ai montré...Ruby 1.9 offre le Tableau#exemple de méthode qui renvoie un élément, ou des éléments sélectionnés au hasard à partir d'un Tableau. Les résultats de #exemple de ne pas inclure le même élément de Tableau à deux reprises.
Comparativement à la
to_a.sort_by
approche, lasample
méthode semble être nettement plus rapide. Dans un scénario simple, j'ai comparé lessort_by
àsample
, et a obtenu les résultats suivants.Oui, il est possible de le faire sans boucle et sans garder trace des numéros ont été choisis. Il a appelé à une Linear Feedback Shift Register: Créer de la Séquence des nombres Aléatoires Sans répétition
Comment agit d'un jeu sur cette? Nombres aléatoires sans avoir à utiliser Ensemble ou de Hachage.
Vous pouvez utiliser une table de hachage pour suivre les nombres aléatoires que vous avez utilisé jusqu'à présent:
Plutôt que d'ajouter des éléments à une liste ou un tableau, les ajouter à un Ensemble.
Si vous avez une liste limitée de possible nombres aléatoires (c'est à dire de 1 à 100), puis de Kent solution est bonne.
Sinon il n'y a pas d'autre bonne façon de le faire sans boucle. Le problème est que vous DEVEZ faire une boucle si vous en obtenir un duplicata. Ma solution doit être efficace et la boucle ne doit pas être trop beaucoup plus que la taille de votre groupe (si vous voulez 20 nombres aléatoires, il peut prendre de 25 itérations en moyenne.) Si le nombre d'itérations est de pire les numéros plus vous avez besoin et le petit max est. Voici mon code ci-dessus modifiée afin de montrer combien d'itérations sont nécessaires pour l'entrée:
Je pourrais écrire ce code ressemble plus à de la Matrice.carte, si vous voulez 🙂
Basé sur Kent Fredric la solution ci-dessus, c'est ce que j'ai fini par utiliser:
Grâce Kent.
Pas de boucles avec cette méthode
Voici une solution:
Supposons que vous voulez que ces nombres aléatoires entre
r_min
etr_max
. Pour chaque élément dans votre liste, de générer un nombre aléatoirer
, et de fairelist[i]=list[i-1]+r
. Ce serait vous donner des nombres aléatoires qui sont de plus en plus monotone, garantissant l'unicité de la condition quer+list[i-1]
n'a pas plus de flux der
> 0Pour le premier élément, vous pouvez utiliser
r_min
au lieu delist[i-1]
. Une fois que vous avez terminé, vous pouvez mélanger de la liste les éléments ne sont pas évidemment dans l'ordre.Le seul problème avec cette méthode est que lorsque vous allez sur
r_max
et ont encore plus d'éléments à générer. Dans ce cas, vous pouvez réinitialiserr_min
etr_max
à 2 adjacentes de l'élément que vous avez déjà calculé, et il suffit de répéter le processus. Effectivement cela fonctionne de la même algorithme sur un intervalle de temps où il n'y a pas les numéros déjà utilisé. Vous pouvez continuer à faire cela jusqu'à ce que vous avez la liste peuplée.Aussi loin qu'il est bon de savoir à l'avance le maximum de valeur, vous pouvez le faire de cette façon:
et vous pouvez obtenir des données aléatoires de cette façon:
vous obtiendrez
nil
lorsque toutes les valeurs seront exausted à partir du pont.Méthode 1
À l'aide de Kent approche, il est possible de générer un tableau de longueur arbitraire en gardant toutes les valeurs dans une gamme limitée:
Méthode 2
Un autre, éventuellement plus efficace, la méthode modifiée de la même Kent une autre réponse:
Sortie