2010-06-23 6 views
4

J'essaie de trouver un moyen de créer des nombres aléatoires qui "se sentent" aléatoires sur de courtes séquences. C'est pour un jeu de quiz, où il y a quatre choix possibles, et le logiciel doit choisir l'un des quatre endroits où mettre la bonne réponse avant de remplir les trois autres avec des distracteurs.Générateur de nombres entiers "feeling" aléatoire pour les séquences courtes

De toute évidence, arc4random % 4 va créer plus que des résultats suffisamment aléatoires sur une longue séquence, mais dans une courte séquence, il est tout à fait possible (et un événement fréquent!) Que cinq ou six du même nombre reviennent à la suite. C'est ce que je vise à éviter. Je ne veux pas non plus simplement dire «ne jamais choisir le même carré deux fois», car cela ne donne que trois réponses possibles pour chaque question, sauf la première. Actuellement, je fais quelque chose comme ceci:

bool acceptable = NO; 
do { 
    currentAnswer = arc4random() % 4; 
    if (currentAnswer == lastAnswer) { 
    if (arc4random() % 4 == 0) { 
     acceptable = YES; 
    } 
    } else { 
    acceptable = YES; 
    } 
} while (!acceptable); 

est-il une meilleure solution à ce que je donne sur?

+0

Je pense que la réponse à cela va dépendre fortement du nombre de "pièces" à 4 côtés dans une rangée, car il n'y a peut-être pas de solution pour une séquence suffisamment courte. Vous avez évoqué le problème de la réduction des degrés de liberté, mais mon intuition me dit que tout processus de sélection post-hoc réduira le DoF. Dans votre exemple, la post-probabilité que A sera suivi par A devient 1/16 au lieu de 1/4 pour A, B. Je m'attends à ce qu'un joueur remarque que même si elle n'a pas remarqué qu'elle a remarqué. Les humains sont vraiment bons (comme le sont les pigeons). – msw

+0

J'aurais dû indiquer que les séquences sont ouvertes. Je pense que pour la plupart des joueurs, ils seront relativement courts (moins de 100), mais en théorie, vous pouvez jouer pendant des heures et passer par des milliers de questions. Je ne pense pas que ce soit trop important, parce que les joueurs ne se souviendront probablement pas de l'enchaînement de plus de quelques questions, bien que, comme vous le dites, ils pourraient bien le remarquer sans s'en apercevoir. :) –

Répondre

3

Si votre question était de savoir comment calculer currentAnswer à l'aide non-itérativement les probabilités de votre exemple, Guffa a votre réponse.

Si la question est de savoir comment éviter Clustering aléatoire sans violer équiprobabilité et vous savez la limite supérieure de la longueur de la liste, il faut considérer l'algorithme suivant qui est un peu comme un tri:

from random import randrange 
# randrange(a, b) yields a <= N < b 

def decluster(): 
    for i in range(seq_len): 
     j = (i + 1) % seq_len 
     if seq[i] == seq[j]: 
      i_swap = randrange(i, seq_len) # is best lower bound 0, i, j? 
      if seq[j] != seq[i_swap]: 
       print 'swap', j, i_swap, (seq[j], seq[i_swap]) 
       seq[j], seq[i_swap] = seq[i_swap], seq[j] 

seq_len = 20 
seq = [randrange(1, 5) for _ in range(seq_len)]; print seq 
decluster(); print seq 
decluster(); print seq 

où toute relation avec le code Python réel est purement fortuite. Je suis à peu près sûr que les probabilités antérieures sont maintenues, et il semble que les grappes de rupture (et parfois en ajoute). Mais je suis assez endormi donc c'est pour des raisons d'amusement seulement.

+0

Génial. J'ai fini par mettre en place quelque chose comme ça. Le jeu est ouvert, donc je ne fais que générer 100 valeurs d'affilée, puis en générer 100 de plus lorsqu'elles sont épuisées. Il se sent certainement plus aléatoire que mon approche. –

+0

Merci pour le problème intéressant. Après une journée de réflexion, je suis à peu près sûr que la commission de jeu de Vegas approuverait cet algorithme comme "uniforme" (en supposant un PRNG décent, qui est arc4). – msw

+0

msw: Je doute qu'ils autorisent l'utilisation d'un PRNG, cryptographiquement sécurisé ou non :-). Je pourrais essayer de créer un décorateur pour nos RNG et exécuter celui-ci à travers nos tests. Mais je pense que si vous évitez le regroupement, vous jetez aussi toute une série de résultats possibles. L'équiprobabilité n'est pas seulement pour le test Monobit, mais vous pouvez également regarder des segments plus grands. Cela étant dit, pour cette question, c'est certainement correct - en général, une mauvaise idée ;-) – Joey

0

Pour réduire la probabilité d'un nombre répété de 25%, vous pouvez sélectionner un nombre aléatoire compris entre 0 et 3,75, puis le faire pivoter de sorte que 0,75 se termine à la réponse précédente.

Pour éviter d'utiliser des valeurs en virgule flottante, on peut multiplier par quatre facteurs:

Pseudo-code (où / est une division entière):

currentAnswer = ((random(0..14) + lastAnswer * 4) % 16)/4 
0

Mettre en place une matrice pondérée. Disons que la dernière valeur était un 2. Faites un tableau comme ceci:

array = [0,0,0,0,1,1,1,1,2,3,3,3,3]; 

Puis choisissez un nombre dans le tableau.

newValue = array[arc4random() % 13]; 

Passez maintenant à l'utilisation de math à la place d'un tableau.

newValue = (((arc4random() % 13)/4) + 1 + oldValue) % 4; 

Pour possibilités P et une utilisation du poids 0<W<=1:

newValue = (((arc4random() % (P/W-P(1-W))) * W) + 1 + oldValue) % P; 

P = 4 et W = 1/4, (P/WP (1-W)) = 13. Cela dit le la dernière valeur sera 1/4 aussi probable que les autres valeurs.

Si vous éliminez complètement la réponse la plus récente, elle sera tout aussi visible que la réponse la plus récente qui apparaît trop souvent. Je ne sais pas quel poids vous conviendra, mais 1/4 est un bon point de départ.

3

Vous remplir un tableau de résultats, puis shuffle, puis les assigner dans cet ordre.

Donc, pour seulement 8 questions:

answer_slots = [0,0,1,1,2,2,3,3] 

shuffle(answer_slots) 

print answer_slots 
[1,3,2,1,0,2,3,0] 
+0

C'est tout aussi susceptible de créer des clusters aléatoires que non. – msw

+0

@msw: Ils seront seulement aussi longs que vous les autorisez, cependant. Si vous mélangez "0..3 * 3", il ne peut y avoir que trois occurrences du même nombre, par exemple. – Joey

+0

Oui, si l'ensemble est seulement de longueur 8, 87% des ensembles possibles ont au moins une adjacence. Dans ce cas, vous ne pouviez pas faire mieux que cela. – msw

Questions connexes