Script aléatoire qui n'est pas réellement aléatoire

106

Comme petite blague dans le bureau, quelqu'un a voulu un script qui choisit un nom au hasard, et cette personne fera une tournée de boissons.

Appelons les gens John, Jeff, Emma, ​​Steve et Julie.

J'ai pensé qu'il serait amusant de créer un script qui semble aléatoire au premier abord, mais qui donne en fait toujours la même personne que la sortie (à vous de choisir).

Le vote le plus voté gagne après une semaine

Et le gagnant est....

Paul R avec (actuellement) 158 votes.

Les réponses sont excellentes, et si quelqu'un d'autre a des idées qui n'ont pas encore été affichées, ajoutez-les, j'aime les lire.

TMH
la source
44
xkcd.com/221
AstroCB
6
@ AstroCB un de mes favoris. Juste derrière les tables de bobby.
Cruncher
50
Il semblerait que ce serait plus sournois si c'était aléatoire, sauf de ne jamais choisir une personne.
Rétablir Monica
6
@AstroCB celui-ci est également fantastique: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb
3
J'ai parcouru la première page: la plupart des réponses choisissent toujours John, le deuxième en haut est Julie, Jeff est choisi rarement et Steve par 1. Même Ray a été choisi par un, mais personne n'a choisi Emma. Morale de l'histoire: lorsque vous vous alignez pour décider au hasard qui achètera les boissons, nommez-vous Emma.
Misérable Variable

Réponses:

171

C

Il est important de décider qui achète le plus rapidement possible afin de ne pas perdre de temps précieux à boire. C est donc le choix évident pour obtenir les performances maximales:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    const char *buyer;
    int n;

    srand(time(NULL)); // make sure we get a good random seed to make things fair !
    n = rand();
    switch (n % 5)
    {
        case 0: buyer = "John";
        case 1: buyer = "Jeff";
        case 2: buyer = "Emma";
        case 3: buyer = "Steve";
        case 4: buyer = "Julie";
    }
    printf("The person who is buying the drinks today is: %s !!!\n", buyer);
    return 0;
}

Explication:

Cela fonctionnerait parfaitement s'il y avait un break;après chaque cas dans l'instruction switch. Dans l’état actuel des choses, chaque cas "échoue", si bien que la pauvre Julie finit toujours par acheter les boissons.

Paul R
la source
17
+1 pour la performance - beaucoup plus rapide que de lancer un dé physique! ;)
Jwosty
16
Je pense à l'optimiser davantage, peut-être avec SIMD ou GPGPU, juste pour obtenir un peu plus de performance. ;-)
Paul R
7
Absolument réel vivre applicable. Personne ne remettrait jamais en cause le moindre accident.
iFreilicht
5
Est-ce juste moi ou est-ce trop évident à repérer?
Alvin Wong
3
@AlvinWong Je ne l'ai pas remarqué tout de suite. Encore une fois, je n'utilise pas C régulièrement, ni aucun autre langage descendant de BCPL.
Rhymoid
164

PHP

Je ne pouvais pas laisser passer ça, alors en voici un autre:

$f = fopen('/dev/random','r');
$s = fread($f, 4);
fclose($f);

$names = ['John', 'Jeff', 'Emma', 'Steve', 'Julie'];

echo $names[$s % count($names)];

En réalité, cela ne garantit pas la production de John, mais les chances sont très bonnes. PHP se fera un plaisir de prendre tout ce que / dev / random a à offrir, sachant qu'il ne peut (probablement) pas l'analyser et donne le nombre très raisonnable 0 à la place. Après tout, alerter le programmeur d'une erreur potentielle est considéré comme un péché mortel en PHP.

monocell
la source
25
Il faut aimer PHP - et même mieux, il est rare qu'il choisisse quelqu'un d'autre. Donc, si vous êtes chanceux, il semblera un peu partial au début
Falco
142
+1000 pour "... avertir le programmeur d'une erreur potentielle est considéré comme un péché meurtrier en PHP."
jsedano
phpsadness obligatoire
applaudissements
85

Haskell

Il est trop transparent s'il renvoie toujours le même nom, alors essayez ce qui suit.

import Control.Monad
import System.Exit
import Control.Concurrent
import Control.Concurrent.MVar


data Person = John | Jeff | Emma | Steve | Julie deriving (Show, Enum)

next Julie = John
next p = succ p

rotate :: MVar Person -> IO ()
rotate mp = modifyMVar_ mp (return . next) >> rotate mp

main :: IO ()
main = do
    mp <- newMVar John
    forkIO $ rotate mp
    putStrLn "Shuffling"
    readMVar mp >>= print
    exitWith ExitSuccess

Chaque fois que vous voulez que ce soit aléatoire:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

Et pour votre cible malheureuse:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

Hugs n'implémente que le multitâche coopératif, le rotatethread ne fonctionnera donc jamais

monocell
la source
24
C'est diabolique!
Daenyth
8
C'est comme photographier un dé qui n'a pas encore cessé de bouger.
Vi.
1
@Vi. C'est une belle analogie. Heureusement, l'utilisation de MVars garantit que l'image ne sera pas floue. :)
monocell
@ Monocell Eh bien, techniquement, même la photo d'un objet en mouvement peut être nette.
ghosts_in_the_code
75

Bash - simplicité maximale

Un exemple très simple: évitons les problèmes en procédant de la manière habituelle. N'oubliez pas d'ensemencer le générateur à partir de l'horloge système pour obtenir un bon résultat!

#!/bin/bash

names=(John Jeff Emma Steve Julie)   # Create an array with the list of names
RANDOM=$SECONDS                      # Seed the random generator with seconds since epoch
number=$((RANDOM % 5))               # Pick a number from 0 to 4
echo ${names[number]}                # Pick a name

Cela $SECONDSsuppose que l'utilisateur ne sache pas ce que fait la fonction intégrée; il retourne le nombre de secondes écoulées depuis le démarrage du shell actuel. Comme c'est dans un script, le shell a toujours commencé il y a zéro seconde. Le générateur est toujours stocké 0et Julie achète toujours la bière.

Prime:

Celui-ci résiste assez bien à l'examen; Si vous entrez le même code sur la ligne de commande plutôt que dans un script, les résultats seront aléatoires, car $SECONDSils renverront la durée d'exécution du shell interactif de l'utilisateur.

Émeute
la source
9
\ o / moyenne !!! Vraiment méchant!!! $SECONDSftw! \ o /
yeti
Qu'est-ce qui se passe si vous sourcecela, au lieu de simplement l'exécuter? Est-ce que le shebang déclenchera toujours une nouvelle coquille ou quelque chose?
jpmc26
1
@ jpmc26: si vous l'exécutez avec sourcealors c'est exactement la même chose que si vous aviez tapé les commandes sur la ligne de commande vous-même; #! / bin / bash est un commentaire donc il est ignoré. Cela est vrai de n'importe quel script.
Riot
57

C #

using System;
using System.Linq;

namespace PCCG {
    class PCCG31836 {
        public static void Main() {
            var names = new string[]{ "John", "Jeff", "Emma", "Steve", "Julie" };
            var rng = new Random();
            names.OrderBy(name => rng.Next());
            Console.WriteLine(names[0]);
        }
    }
}

Cela pourrait ne pas duper ceux qui sont familiers avec l’API .Net, mais ceux qui ne le savent pas pourraient croire que cela OrderBymodifie l’objet sur lequel vous l’appelez et c’est une erreur plausible pour un débutant dans l’API.

Peter Taylor
la source
1
Même si OrderBy modifiait hypothétiquement l'objet, cet appel trierait-il la liste au hasard? En tant que personne non familiarisée avec .NET, ma première hypothèse était que, puisqu'il rng.Next()n'est appelé qu'une fois, le tableau serait trié par une constante, ce qui n'entraînerait aucun changement (ou un changement qui dépend uniquement de l'algorithme de tri).
Brilliand
1
@Brilliand L'argument transmis à OrderBy n'est pas une valeur statique, il est exécuté à chaque fois qu'un élément est trié et, dans ce cas, renvoie des valeurs aléatoires sans comparaison de valeurs. En fait, cela fonctionnerait correctement si la ligne étaitnames = names.OrderBy(name => rng.Next());
user3188175
1
Le =>signe qu'il s'agit d'une expression lambda en C # (fermeture).
Snowbody
44

PowerShell

$names = @{0='John'; 1='Jeff'; 2='Emma'; 3='Steve'; 4='Julie'}
$id = random -maximum $names.Length
$names[$id]

Ce sera toujours la sortie John.

$namesest un System.Collections.Hashtablequi n'a pas de Lengthpropriété. À partir de PowerShell v3, Length(et aussi Count) peut être utilisé comme propriété sur n’importe quel objet. Si un objet n'a pas la propriété, il retournera 1quand l'objet ne sera pas nul, sinon il retournera 0. Donc, dans ma réponse, $names.Lengthévalue à 1 et random -maximum 1renvoie toujours 0 puisque le maximum est exclusif.

Rynant
la source
42

Q

show rand `John`Jeff`Emma`Steve`Julie;
exit 0;

Q initialise toujours sa graine de nombre aléatoire avec la même valeur.

skeevey
la source
8
Donc en gros, ce n'est pas aléatoire du tout
Sam Creamer
3
@SamCreamer Le but de la question est de rendre la sortie non aléatoire. Mais ça a l'air aléatoire alors ça convient parfaitement
Cruncher
4
Désolé, je voulais dire que les nombres aléatoires de Q ne sont pas si aléatoires, cette question répond certainement aux critères. N'a pas voulu dire de cette façon!
Sam Creamer
Oui, alors vous devez trouver votre propre façon de générer une graine aléatoire chaque fois que vous voulez utiliser rand? Cela semble ... utile.
DLeh
1
Peut définir la graine aléatoire manuellement très facilement ... lancez l'interprète avec l' -S 1234option ou faites-le à \S 1234partir de l'interprète
skeevey le
34

Perl

use strict;

my @people = qw/John Jeff Emma Steve Julie/;
my @index = int(rand() * 5);

print "Person @index is buying: $people[@index]\n";

Impressions: Person X is buying: Jeff(où X est compris entre 0 et 4)

Abuser un peu du contexte scalaire. @index = int(rand() * 5)place un nombre entier aléatoire compris entre 0 et 4 à la 0ème position de la @indexliste. Lors de l'impression du tableau, il imprime correctement l'entier aléatoire dans @index, mais lorsqu'il est utilisé comme index de tableau dans $people[@index], @index utilise un contexte scalaire, ce qui lui donne la valeur de la taille de la liste, c'est-à-dire 1.

Fait intéressant, @people[@index]il indexe correctement.

Il @people[@index]est intéressant de noter qu’une tranche de hachage en Perl @indexest évaluée dans le contexte de la liste; dans ce cas, c'est une liste à une seule entrée et c'est pourquoi cela fonctionne correctement

Allen G
la source
Donc, en termes C (++), il y a une conversion implicite de liste en scalaire car, lors de l'indexation, un scalaire est attendu?
iFreilicht
@ iFreilicht Correct. En Perl, les expressions peuvent être évaluées sous forme de liste ou de scalaire, selon l'endroit où elles apparaissent. Par conséquent, la même expression peut signifier différentes choses, selon le contexte. Une variable de liste (c'est-à-dire une variable avec le @préfixe), dans "list context", est interprétée comme tous ses éléments, mais dans "scalar context", est un scalaire égal au nombre total d'éléments de la liste. Par conséquent, à l'intérieur de la chaîne, la variable de liste a un contexte de liste et est interpolée, et nous obtenons Person X is buying. Mais en tant qu'indice de tableau, il obtient un contexte scalaire et est interprété comme 1.
Allen G
3
Le problème avec ceci est que quand un programmeur Perl voit my @index = ..., il se demande immédiatement "WTF ?!".
derobert
@derobert, pourquoi vous demandez-vous? Vous voyez un code comme ça assez souvent ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;etc.
Matthias
@Matthias parce que la ligne doit choisir et stocker une valeur unique, et au lieu d'un scalaire, elle est stockée dans un tableau.
derobert
23

ECMAScript

// Randomly pick a person on only one line!
var people = [('John', 'Jeff', 'Emma', 'Steve', 'Julie')];

console.log(people[new Date() % people.length | 0]);

Il choisit toujours Julie.

Il a des crochets entre les crochets et l'opérateur de virgule renvoie la valeur de son opérande droit.
C'est aussi très facile à manquer. Je l'ai manqué auparavant dans le code réel .

Brosse à dents
la source
C'est délicieux. Enfin, une utilisation pour ce terrible, terrible opérateur.
Keen
5
La virgule dans ce contexte est techniquement un opérateur plutôt qu'un séparateur. ecma-international.org/ecma-262/5.1/#sec-11.14 Et c'est terrible. Sauf si vous voulez que votre code soit difficile à lire. Comme vous le faites ici. Alors, bravo.
Keen
2
@Cory Oui, je suis d'accord - bien que je l'utilise tout le temps pour Code Golf avec des expressions de fonction (par exemple (a,b)=>(a=b[0],b)). J'ai clarifié ma réponse.
Brosse à dents
21

C #

using System;

namespace LetsTroll {
    class Program {
        static void Main() {
            var names = new string[]{ "John", "Jeff", "Emma", "Steve", "Julie" };
            var random = new Random(5).NextDouble();
            var id = (int)Math.Floor(random);
            Console.WriteLine(names[id]);
        }
    }
}

Le truc, c'est que la méthode new Random().NextDouble()retourne un double entre 0 et 1. En appliquant Math.Floor()cette valeur, elle sera toujours égale à 0.

Knerd
la source
24
Il n'a pas résisté à mon rapide coup d'œil. ;)
Martin Ender
1
@TimS. comme ça? : P
Knerd
2
+1, beaucoup mieux - Je sais ce que vous faites vraiment, mais cela pourrait tromper quelqu'un qui n'est pas trop familier avec l'API.
Tim S.
1
Je ne sais pas à ce sujet. Si vous allez spécifier une graine, pourquoi ne pas simplement utiliser la bonne façon d'obtenir un "aléatoire" int:var random = new Random(5); var id = random.NextInt(5);
clcto
2
@clcto À mon avis, l'inclure deux fois est plus susceptible d'inciter quelqu'un à faire une double prise, à demander pourquoi et à voir le problème. L'inclure une fois, puis l'inclusion de code inutile par la suite, donne un peu de redirection / sournois. Bonus: si quelqu'un corrige l'un des bugs, un autre existe.
Tim S.
18

C #

var names = new string[] {"John", "Jeff", "Emma", "Steve", "Julie"};
var guidBasedSeed = BitConverter.ToInt32(new Guid().ToByteArray(), 0);
var prng = new Random(guidBasedSeed);
var rn = (int)prng.Next(0, names.Length);
Console.WriteLine(names[rn]);

Allusion:

Générer une graine à partir du GUID. Les Guids ont 4 × 10−10 chances de collision. Super aléatoire.

Répondre:

Au moins quand vous utilisez Guid.NewGuid(), oups! (Façon sournoise de faire des graines toujours 0). Aussi inutile (int) pour les erreurs de direction.

Nathan Cooper
la source
L’autre façon de le faire est d’être AddRangeembrouillé Concatlors de l’ajout de noms à un List<string>. Il m'est arrivé d'avoir un hachage avec un IEqualityComparer sournois, mais ce serait bien trop inhabituel. À mon crédit, il n'y avait pas beaucoup (le cas échéant) de réponses basées sur les semences lorsque j'ai posté ceci.
Nathan Cooper
J'imagine que vous aviez la même idée que moi, mais vous étiez un peu plus rapide et rendiez cela un peu plus difficile à voir. +1!
Tsavinho
7
Séduire le générateur de nombres aléatoires est une astuce évidente, mais vous l'avez brillamment caché ici. Beau travail.
TRiG
18

bash / coreutils

Ceci est repris presque textuellement d'un script que j'ai écrit dans un but similaire.

#!/bin/bash
# Sort names in random order and print the first
printf '%s\n' John Jeff Emma Steve Julie | sort -r | head -1

Même oublier d’utiliser une majuscule R est une erreur que j’ai occasionnellement commise dans des scripts réels.

Kasperd
la source
3
Pourriez-vous donner une meilleure explication? Votre version actuelle est très courte et n’est pas utile pour quelqu'un qui ne connaît pas vraiment bash.
iFreilicht
6
-rspécifie le tri inverse (lexicographique), donc Steve sera toujours sélectionné. Cela pourrait être vu comme une typo innocente ou -Rpour une sorte aléatoire
Max
3
C'est un bon rappel de ne pas faire confiance aux commentaires, mais de lire attentivement le code!
TecBrat
16

Rubis

names = ["John", "Jeff", "Emma", "Steve", "Julie"]

puts names.sort{|x| rand()}.first

Cela fonctionnerait correctement avec sort_by, mais sortattend une fonction de comparaison qui fonctionne comme <=>. Le résultat de rand () sera toujours positif, il produira donc toujours des résultats équivalents à condition que l' sortalgorithme de votre implémentation Ruby soit déterministe. Mon Ruby 1.9.3 affiche toujours Julie.

histocrate
la source
12

Rubis

names = ["John", "Jeff", "Emma", "Steve", "Julie"]

puts names[rand() % 5]

rand() sans argument produit un flottant aléatoire compris entre 0 et 1. Ainsi, modulo 5 ne fait rien, et lorsque vous découpez un tableau avec un argument float, Ruby arrondit le résultat à la baisse, renvoyant ainsi toujours John.

histocrate
la source
11

Perl

trois srands le rendra trois fois plus aléatoire!

#!perl
use feature 'say';

sub random_person {
    my ($aref_people) = @_;
    srand; srand; srand;
    return $aref_people->[$RANDOM % scalar @$aref_people];
}

my @people = qw/John Jeff Emma Steve Julie/;
my $person = random_person(\@people);

say "$person makes next round of drinks!";

explication

Il n'y a pas de $ RANDOM dans Perl, c'est une variable non définie. le code retournera toujours le premier élément de la liste - les boissons sur John :)

modifier:

après avoir lu le code, l’un des cinq gars a décidé de corriger l’erreur évidente en produisant le programme suivant:

#!perl
use feature 'say';

sub random_person {
    my ($aref_people) = @_;
    return $aref_people->[rand $#$aref_people];
}

my @people = qw/John Jeff Emma Steve Julie/;
my $person = random_person(\@people);

say "$person buys next round of drinks!";

pouvez-vous dire qui l'a fait juste en regardant le code?

explication:

en Perl, $#arrayretourne l'index du dernier élément; étant donné que les tableaux sont basés sur zéro, étant donné une référence à un tableau avec cinq éléments, $#$aref_peoplesera 4.
randrenvoie un nombre aléatoire supérieur ou égal à zéro et inférieur à son paramètre, ainsi il ne reviendra jamais 4, ce qui signifie en fait que Julie n'achètera jamais de boissons :)

goth perl chinois
la source
1
$RANDOMest une vraie fonctionnalité dans bash, ksh et zsh (mais pas en perl).
kernigh
10

Python

Tout le monde sait que vous ne pouvez pas faire confiance au hasard dans un si petit espace échantillon; pour le rendre vraiment aléatoire, j'ai abandonné la méthode obsolète de choisir un nom dans une liste et mon programme épelera un nom complètement aléatoire. Comme la plupart des noms dans le bureau avaient 4 lettres, nous nous en contenterons.

import random

def CHR (n):
    # Just easily convert a number between 0 and 25 into a corresponding letter
    return chr(n+ord('A'))

# Seed the RNG with a large prime number. And multiply it by 2 for good measure.
random.seed (86117*2)

# Now, let's see what COMPLETELY RANDOM name will be spelled out!
totallyRandomName = ''
for i in range(4) :
    totallyRandomName += CHR(int(random.random()*26))

print (totallyRandomName)

Naturellement, j’ai fait quelques travaux de préparation pour que je puisse choisir la bonne graine.

Tal
la source
15
Semer le nombre aléatoire généré avec une constante est tout simplement trop évident ..
Rétablir Monica
@BrendanLong Cela soulèverait certainement des sourcils. Les gens voudraient le tester pour s'assurer qu'il est aléatoire. Et quand ce n'est pas le cas, devinez qui achète des boissons.
JFA
10

C

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
char *name[]={"John", "Jeff", "Emma", "Steeve", "Julie"};

int i;
int n=rand()%10000;
int r=3;

for (i=0; i<10000+n; i++) // random number of iteration
    {
    r=(r*r)%10000; // my own PRNG (square and mod)
    }

printf("%s", name[r%5] );
}

Désolé, Jeff!

Après quelques itérations r == 1 mod 5, à cause des maths. Moralité: n'écris pas ton propre PRNG si tu es mauvais en maths. :)

Cpri
la source
10

C ++ x11

#include <vector>
#include <iostream>

int main () {
  std::srand(time(NULL));
  std::vector<std::string> choice{("jen","moss","roy")};
  std::cout << choice[rand()%choice.size()] << std::endl;
}

La taille du vecteur est en fait de 1 en raison de la parenthèse utilisée dans la liste des initialiseurs. L’exploitant comma supprimera tous les noms et renverra le dernier; l’acheteur est donc toujours Roy.

tomasz
la source
10

Scala

Je sais que mes utilisateurs seront sceptiques, j'ai donc inclus une preuve que mon caractère aléatoire est vraiment juste!

object DrinkChooser {

  def main(args: Array[String]): Unit = {
    proveRandomness()
    val names = List("John","Jeff","Emma","Steve","Julie")
    val buyer = names(randomChoice(names.size))
    println(s"$buyer will buy the drinks this time!")
  }

  def proveRandomness(): Unit = {
    val trials = 10000
    val n = 4
    val choices = for (_ <- 1 to 10000) yield randomChoice(n)
    (choices groupBy(identity)).toList.sortBy(_._1) foreach { case (a, x) =>
      println(a + " chosen " + (x.size * 100.0 / trials) + "%")
    }
  }

  def randomChoice(n: Int): Int = {
    var x = 1
    for (i <- 1 to 1000) { // don't trust random, add in more randomness!
      x = (x * randomInt(1, n)) % (n + 1)
    }
    x
  }

  // random int between min and max inclusive
  def randomInt(min: Int, max: Int) = {
    new scala.util.Random().nextInt(max - min + 1) + min
  }

}

Un exemple exécuté:

1 chosen 25.31%
2 chosen 24.46%
3 chosen 24.83%
4 chosen 25.4%
John will buy the drinks this time!

À moins que quelqu'un d'autre ait beaucoup de chance, John achètera toujours les boissons.

La "preuve" de l’aléatoire repose sur le fait qu’elle rand(1, 4) * rand(1, 4) % 5est toujours également répartie entre 1 et 4 inclus. Mais rand(1, 5) * rand(1, 5) % 6est dégénéré. Il est possible que vous obteniez un 0, ce qui donnerait le résultat final 0 indépendamment du reste de "l'aléatoire".

Joe K
la source
10

Javascript (avec Underscore.js )

Comme javascript n’a pas de shuffle intégré, nous utiliserons Underscore.js

var people = ['John', 'Jeff', 'Emma', 'Steve', 'Julie'];
_.shuffle(people); // Shuffle the people array
console.log("Next round is on", people[0]);

_.shuffle renvoie le tableau mélangé, il ne le modifie pas en tant que Array.prototype.sort () , désolé John

Kristoffer Sall-Storgaard
la source
9

JavaScript

Deuxième essai, celui-ci est un peu plus compliqué:

var getRandomEntry = function(args){
    return args[Math.floor(Math.random() * arguments.length)]; 
}

alert(getRandomEntry(["peter","julie","samantha","eddie","mark"]));

La argumentsvariable est localement accessible pour les fonctions et est un tableau de tous les arguments transmis à la fonction. En utilisant un simple nommage et en transmettant un tableau à la fonction elle-même, vous pouvez vérifier que nous ne prenons pas la longueur du tableau, mais bien la longueur de la liste des arguments (qui est 1). Cela peut être encore mieux exécuté en utilisant des caractères spéciaux ou un type de police.

thomaux
la source
Ce n'était pas le plus difficile à repérer. Quiconque a construit une Nfonction -ary arbitraire en JavaScript connaît la argumentsvariable.
Conor O'Brien
8

C ++

Pour être juste, nous devrions faire beaucoup d'essais et choisir celui qui est sélectionné le plus souvent.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <map>

static const char *names[] = { "John", "Jeff", "Emma", "Steve", "Julie" };

int main() {
    srand(time(NULL));
    std::map<int, int> counts;

    // run 2^31 trials to ensure we eliminate any biases in rand()
    for (int i = 0; i < (1<<31); i++) {
        counts[rand() % (sizeof(names)/sizeof(*names))]++;
    }

    // pick the winner by whomever has the most random votes
    int winner = 0;
    for (std::map<int, int>::const_iterator iter = counts.begin(); iter != counts.end(); ++iter) {
        if (iter->second > counts[winner]) {
            winner = iter->first;
        }
    }

    printf("%s\n", names[winner % (sizeof(names)/sizeof(*names))]);
}

Quelle est la valeur de 1<<31? Désolé, John.

duveteux
la source
La réponse à votre question spoiler est UB. Je suis indécis si cela fait mieux ou pire.
nwp
@nwp Eh bien, bien sûr, mais il est toujours vrai que int est un complément de 32 bits à 2, ce qui semble être le cas même sur 64 bits (avec gcc). Je n'ai pas testé sur Clang, cependant.
moelleux
Non, cela ne tient pas partout où un int est un complément de 32, mais 2. La valeur de 1 << 31 n'est pas définie. Cependant, vous avez de la chance, le compilateur choisit ce que vous voulez et, comme il est fait pour la rapidité, il décidera simplement de ne rien faire, ce qui s'avère être ce que vous voulez.
nwp
@ nwp 1<<31 == 0x80000000peu importe la définition même de <<, et sur le complément de 32 bits 2, c'est INT_MIN. Pensez-vous peut-être à 1<<32ce qui peut ou non == 0? (Parce que sur x86, 1<<32évalue généralement à 1 ...)
moelleux
@nwp C'est en fait défini par l'implémentation. Maintenant, si nous parlions de C, alors ce serait indéfini.
Stuart Olsen
7

T-SQL (2008+)

SELECT TOP 1 name
FROM
 (VALUES('John'),('Jeff'),('Emma'),('Steve'),('Julie')) tbl(name)
ORDER BY RAND()

Explication:

Dans MS SQL Server, RAND()n'évalue qu'une fois par exécution. Chaque nom se voit toujours attribuer le même numéro, en laissant l'ordre original. John est le premier. Suce pour John.

Amélioration suggérée:

T-SQL peut produire une qualité décente, avec des nombres aléatoires par ligne RAND(CHECKSUM(NEWID())).

confortablydrei
la source
Je pense que ORDER BY NEWID () suffira (pas besoin de CHECKSUM)
Jacob
7

Lua

buyer={'John', 'Jeff', 'Emma', 'Steve', 'Julie'}
   -- use clock to set random seed
math.randomseed(os.clock())
   -- pick a random number between 1 and 5
i=math.random(5)
io.write("Today's buyer is ",buyer[i],".\n")

os.clock()est à des fins de synchronisation, os.time()est ce qui devrait être utilisé avec math.randomseedpour bon RNG. Malheureusement, Julie achète toujours (du moins sur mon ordinateur).

Kyle Kanos
la source
math.random()sans argument renvoie également un nombre dans la plage [0,1). -1 pour ne pas attraper ça.
Mniip
@mniip: vraiment mérité aussi! Je l'ai corrigé maintenant.
Kyle Kanos
6

Idiomatic C ++ 11

Lorsque des boissons sont en jeu, il est particulièrement important d’être à jour avec les normes et les styles de codage les plus récents. c’est un excellent exemple de sélecteur de noms C ++ 11 extrêmement efficace et conforme aux normes idiomatiques.

Elle est générée à partir de l'horloge système et la sort avec le nom pour vérification à chaque fois.

#include <vector>
#include <chrono>
#include <random>
#include <iostream>

auto main()->int {
  std::vector<std::string> names;           // storage for the names
  names.reserve(5);                         // always reserve ahead, for top performance
  names.emplace_back("John");               // emplace instead of push to avoid copies
  names.emplace_back("Jeff");
  names.emplace_back("Emma");
  names.emplace_back("Steve");
  names.emplace_back("Julie");

  std::mt19937_64 engine;                   // make sure we use a high quality RNG engine
  auto seed((engine, std::chrono::system_clock::now().time_since_epoch().count()));  // seed from clock
  std::uniform_int_distribution<unsigned> dist(0, names.size() - 1);     // distribute linearly
  auto number(dist(engine));                // pick a number corresponding to a name
  std::string name(names.at(number));       // look up the name by number
  std::cout << "Seed: " << seed << ", name: " << name << std::endl;  // output the name & seed
  return EXIT_SUCCESS;                      // don't forget to exit politely
}

Essayez ceci en direct: http://ideone.com/KOet5H

Ok, c’est donc un très bon code dans l’ensemble; il y a beaucoup de harengs rouges pour vous faire regarder le code de trop près pour remarquer l'évidence - que le GNA n'est jamais réellement ensemencé :) Dans ce cas, il seeds'agit simplement d'un entier, et bien qu'il semble être enginepassé en tant que paramètre à un fonction de semis, il est en fait simplement ignoré. La variable de départ est définie à partir de l'horloge. Elle peut donc être insérée à la fin avec le nom pour ajouter une insulte à la blessure, mais ce sera toujours Steve qui achète les boissons.

Émeute
la source
1
Cela me tue de ne pas utiliser de liste d'initialisation pour les noms. À tout le moins, vous avez sans aucun doute réussi à fournir du code qui semble trop complexe. Je ne peux pas dire si c'est à cause de la "conformité" ou de tous les commentaires sur le bruit: P
vmrob Le
6

JavaScript

console.log(["Jeff", "Emma", "Steve", "Julie"][Math.floor(Math.random(5))]);

Eh bien, désolé, Math.randomne prend pas de paramètre et renverra toujours un nombre de [0, 1). Pourtant, c'est une fonction variadique heureuse et ne se plaint pas d'arguments!

Bergi
la source
5

Python

names=["John", "Jeff", "Emma", "Steve", "Julie"]
import random # Import random module
random.seed(str(random)) # Choose strictly random seed
print(random.choice(names)) # Print random choice

str (random) donne une chaîne constante; pas une valeur aléatoire

QuadrExAtt
la source
6
Remarque quelque peu non pertinente: si vous utilisez Python 3.2 ou une version ultérieure, le deuxième argument random.seed()doit être 2(valeur par défaut). Si vous réussissez version=1, le nom hash()de la chaîne sera utilisé comme une valeur de départ au lieu de la totalité de la chaîne. Etant donné que Python génère de manière aléatoire les valeurs de hachage des chaînes à partir de 3.2, vous obtiendrez un nom réellement aléatoire.
Blacklight Shining
5

Perl

Emma ferait mieux de ne pas oublier son sac à main! Fonctionne sous strictet warnings.

use strict;
use warnings;

# Use a hash to store names since they're more extendible

my %people;
$people{$_}++ for qw/John Jeff Emma Steve Julie/;

print +(@_=%people)[rand@_];  # 'cos (keys %people)[rand( keys %people )]
                              # is just too long-winded.

Explication ici .

Zaid
la source
Perl 5.18 a quelque peu changé cela en introduisant la randomisation par clé de hachage (pour éviter les attaques complexes par collision de hachage).
Konrad Borowski
4

JavaScript

function getDrinksBuyer(){ 
    var people = ["Jeff", "Emma", "Steve", "Julie"];
    var rand = Math.random(0,4)|0;
    return people[rand];
}

Les |0résultats sont à 0 tout le temps, mais on dirait qu'ils font d'autres arrondis.

Mat
la source
Je l'aime. Bien que je ferais parseInt(Math.random(0, 4))et peut-être ajouter des commentaires comme - Math.randomretourne un double, convertissez-le donc d'abord en entier
Claudiu
5
Le truc, c’est qu’en réalité, nous Math.randomne tenons pas compte de nos maigres paramètres. Il choisit les numéros à sa manière. elle |0arrondit correctement le résultat inattendu et ne constitue donc pas une source de tromperie.
Keen
|0C’est très évident pour certains (nous tous, probablement), mais je parierais que beaucoup n’ont aucune idée de ce qu’il fait. C'est le groupe sur lequel je m'appuyais.
Matt
3
@ Matt je veux dire que |0 , si vous savez ce qu'il fait, ressemble il est arrondi vers le bas, et il est arrondi vers le bas, il est donc pas une tromperie. (Et si quelqu'un n'a aucune idée de ce qu'il |0fait, le code trompeur ne sert à rien; vous pouvez simplement lui dire ce que vous voulez qu'il croie.) Au lieu de cela, le comportement inattendu de votre réponse est basé sur le fait qu'il Math.random(0,4)est fonctionnellement identique à Math.random(), parce que Math.randomn'utilise pas de paramètres.
Keen
4

J

;(?.5) { 'John'; 'Jeff'; 'Emma'; 'Steve'; 'Julie'

Pauvre Julie ... Question: ça aurait pu être le J le plus propre que j'ai jamais écrit ...

Ce code est en fait correct, sauf pour une chose. ?.est l'uniforme rng: ?.5sera toujours retourner 4. ?5aurait été correct.

ıʇǝɥʇuʎs
la source