Zufälliges Skript, das eigentlich nicht zufällig ist


106

Als kleiner Scherz im Büro wollte jemand ein Skript, das zufällig einen Namen auswählt, und diese Person wird eine Runde Getränke machen.

Nennen wir die Leute John, Jeff, Emma, ​​Steve und Julie.

Ich dachte, es wäre lustig, ein Skript zu erstellen, das auf den ersten Blick zufällig erscheint, aber tatsächlich immer die gleiche Person wie die Ausgabe enthält (Sie entscheiden selbst, wen Sie wählen).

Die Antwort mit der höchsten Stimmenzahl gewinnt nach einer Woche

Und der Gewinner ist....

Paul R mit (derzeit) 158 Stimmen.

Die Antworten hier sind großartig, und wenn jemand andere Ideen hat, die noch nicht veröffentlicht wurden, fügen Sie sie bitte hinzu. Ich liebe es, sie durchzulesen.



6
@AstroCB einer meiner Favoriten. Direkt hinter den Bobbytischen.
Cruncher

50
Es scheint, als wäre es hinterhältiger, wenn es zufällig wäre, außer dass niemals eine Person ausgewählt würde.
Brendan Long

6
@AstroCB dieses ist auch fantastisch: dilbert.com/strips/comic/2001-10-25
Gilbertohasnofb

3
Ich ging die erste Seite durch: Die meisten Antworten wählten immer John, die zweithöchste Julie, Jeff wurde selten und Steve mit 1 bewertet. Selbst Ray wurde von einem ausgewählt, aber niemand wählte Emma. Moral der Geschichte: Wenn Sie in einer Schlange stehen und zufällig entscheiden, wer die Getränke kauft, nennen Sie sich Emma.
Miserable Variable

Antworten:


171

C

Es ist wichtig zu entscheiden, wer so schnell wie möglich kauft, um keine kostbare Trinkzeit zu verschwenden - daher ist C die offensichtliche Wahl, um maximale Leistung zu erzielen:

#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;
}

Erläuterung:

Dies würde gut funktionieren, wenn break;in der switch-Anweisung nach jedem Fall eine steht . So wie es aussieht, "fällt" jeder Fall zum nächsten durch, so kauft die arme Julie am Ende immer die Getränke.


17
+1 für Leistung - viel schneller als ein physischer Würfelwurf! ;)
Jwosty

16
Ich denke darüber nach, es weiter zu optimieren, vielleicht mit SIMD oder GPGPU, um ein bisschen mehr Leistung zu erzielen. ;-)
Paul R

7
Absolut real live anwendbar. Niemand würde jemals in Frage stellen, dass es im geringsten ein Unfall war.
iFreilicht

5
Bin es nur ich oder ist das zu offensichtlich, um es zu erkennen?
Alvin Wong

3
@AlvinWong Ich habe es nicht sofort bemerkt. Andererseits verwende ich nicht regelmäßig C oder eine andere Sprache, die von BCPL abstammt.
Rhymoid

164

PHP

Konnte das nicht loslassen, also hier ist noch einer:

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

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

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

Dies ist eigentlich nicht garantiert, um John zu produzieren, aber die Chancen stehen sehr gut. PHP nimmt gerne das, was / dev / random zu bieten hat, um zu sehen, dass es es (wahrscheinlich) nicht analysieren kann und liefert stattdessen die sehr vernünftige Zahl 0. Schließlich wird es in PHP als tödliche Sünde angesehen, den Programmierer auf einen möglichen Fehler aufmerksam zu machen.


25
Sie müssen PHP lieben - und noch besser, es wird manchmal selten jemand anderes wählen. Wenn Sie also Glück haben, scheint es zunächst ein wenig voreingenommen zu sein
Falco

142
+1000 für "... das Warnen des Programmierers auf einen möglichen Fehler wird in PHP als Todsünde angesehen."
Jsedano


85

Haskell

Es ist zu transparent, wenn immer derselbe Name zurückgegeben wird. Versuchen Sie Folgendes

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

Wann immer Sie wollen, dass es zufällig ist:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

Und für dein unglückliches Ziel:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

Hugs implementiert nur kooperatives Multitasking, sodass der rotateThread niemals ausgeführt wird


24
Das ist teuflisch!
Daenyth

8
Fühlt sich an, als würde man einen Würfel fotografieren, der sich noch nicht bewegt.
Vi.

1
@Vi. Das ist eine schöne Analogie. Zum Glück garantiert die Verwendung von MVars, dass das Bild nicht unscharf wird. :)
Monocell

@monocell Nun, technisch gesehen kann sogar ein Foto eines sich bewegenden Objekts klar sein.
ghosts_in_the_code

75

Bash - maximale Einfachheit

Ein sehr einfaches Beispiel - lassen Sie uns Probleme vermeiden, indem Sie es wie im Lehrbuch machen. Vergessen Sie nicht, den Generator von der Systemuhr zu trennen, um ein gutes Ergebnis zu erzielen!

#!/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

Dies setzt $SECONDSvoraus, dass der Benutzer nicht weiß, was das eingebaute Programm tatsächlich tut. Gibt die Anzahl der Sekunden seit dem Start der aktuellen Shell zurück. Wie es in einem Skript steht, hat die Shell immer vor null Sekunden begonnen, sodass der Generator immer voll ist 0und Julie immer das Bier kauft.

Bonus:

Dieser hält der Prüfung ziemlich gut stand; Wenn Sie denselben Code in der Befehlszeile anstatt in einem Skript eingeben, werden zufällige Ergebnisse ausgegeben, da $SECONDSdie Ausführungsdauer der interaktiven Shell des Benutzers zurückgegeben wird.


9
\ o / Mean !!! Wirklich gemein!!! $SECONDSftw! \ o /
yeti

Was passiert, wenn Sie sourcedies tun, anstatt es nur auszuführen? Wird der Schebang immer noch eine neue Muschel auslösen oder so?
jpmc26

1
@ jpmc26: Wenn Sie es mit ausführen, sourceist es genau so, als ob Sie die Befehle in der Befehlszeile selbst eingegeben hätten. #! / bin / bash ist ein Kommentar, der ignoriert wird. Dies gilt für jedes Skript.
Aufstand

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]);
        }
    }
}

Dies täuscht möglicherweise nicht diejenigen vor, die mit der .Net-API vertraut sind, aber diejenigen, die es nicht kennen, glauben möglicherweise, dass dies OrderBydas Objekt, für das Sie es aufrufen , ändert, und es ist ein plausibler Fehler für einen Neuling der API.


1
Selbst wenn OrderBy das Objekt hypothetisch modifizieren würde, würde dieser Aufruf die Liste tatsächlich zufällig sortieren? Da ich mit .NET nicht vertraut bin, war meine erste Vermutung, dass rng.Next()das Array , da es nur einmal aufgerufen wird, nach einer Konstanten sortiert wird, was zu keiner Änderung führt (oder zu einer Änderung, die nur vom Sortieralgorithmus abhängt).
Brilliand

1
@Brilliand Das an OrderBy übergebene Argument ist kein statischer Wert. Es wird jedes Mal ausgeführt, wenn ein Element sortiert wird. In diesem Fall werden zufällige Werte zurückgegeben, ohne dass Werte verglichen werden. Es würde tatsächlich richtig funktionieren, wenn die Zeile names = names.OrderBy(name => rng.Next());
lauten

1
Das =>zeigt an, dass dies ein C # -Lambda-Ausdruck (Closure) ist.
Snowbody

44

Power Shell

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

Dies wird immer ausgegeben John.

$namesist eine, System.Collections.Hashtabledie keine LengthEigenschaft hat. Ab PowerShell v3 kann Length(und Countkann) für jedes Objekt als Eigenschaft verwendet werden. Wenn ein Objekt nicht über die Eigenschaft verfügt, wird es zurückgegeben, 1wenn das Objekt nicht null ist, andernfalls wird es zurückgegeben 0. In meiner Antwort wird also $names.Length1 ausgewertet und es wird random -maximum 1immer 0 zurückgegeben, da das Maximum exklusiv ist.


42

Q.

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

Q initialisiert seinen Zufallszahlen-Startwert immer mit demselben Wert.


8
Im Grunde ist es also überhaupt nicht zufällig
Sam Creamer

3
@SamCreamer Der Zweck der Frage besteht hauptsächlich darin, die Ausgabe nicht zufällig zu machen. Aber das sieht zufällig aus, also passt es definitiv in die Rechnung
Cruncher

4
Tut mir leid, ich habe gemeint, dass die Zufallszahlen von Q nicht so zufällig sind. Diese Frage erfüllt mit Sicherheit die Kriterien. Wollte nicht so rüberkommen!
Sam Creamer

Ja, Sie müssen also jedes Mal, wenn Sie rand verwenden möchten, Ihren eigenen Weg finden, um einen zufälligen Startwert zu generieren? Klingt ... nützlich.
DLeh

1
Kann den Zufallssamen sehr einfach manuell setzen ... -S 1234\S 1234
starte

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";

Ausdrucke: Person X is buying: Jeff(wobei X von 0-4 ist)

Skalarkontext ein wenig missbrauchen. @index = int(rand() * 5)Setzt eine zufällige Ganzzahl von 0 bis 4 an die 0-te Stelle der @indexListe. Beim Drucken des Arrays wird die zufällige Ganzzahl in @index ordnungsgemäß gedruckt. Bei Verwendung als Array-Index in $people[@index]@index wird jedoch ein skalarer Kontext verwendet, der den Wert der Listengröße angibt, d 1. H.

Interessanterweise @people[@index]macht es richtig indizieren.

Interessanterweise @people[@index]ist ein Hash-Slice in Perl und wird daher im Listenkontext @indexausgewertet. In diesem Fall handelt es sich um eine einzelne Eintragsliste, weshalb sie ordnungsgemäß funktioniert


In C (++) findet also eine implizite Konvertierung von Liste zu Skalar statt, da bei der Indizierung ein Skalar erwartet wird?
iFreilicht

@iFreilicht Richtig. In Perl können Ausdrücke als Liste oder als Skalar ausgewertet werden, je nachdem, wo sie angezeigt werden. Infolgedessen kann ein und derselbe Ausdruck je nach Kontext unterschiedliche Bedeutungen haben. Eine Listenvariable (dh eine Variable mit dem @Präfix) wird im "Listenkontext" als alle ihre Elemente interpretiert, im "skalaren Kontext" ist sie jedoch ein Skalar, der der Gesamtzahl der Elemente in der Liste entspricht. Daher hat die Listenvariable innerhalb des Strings einen Listenkontext und wird interpoliert, und wir erhalten Person X is buying. Als Array-Index erhält er jedoch einen skalaren Kontext und wird als 1 interpretiert.
Allen G

3
Das Problem dabei ist, dass ein Perl-Programmierer, der es sieht my @index = ..., sofort "WTF ?!" fragt.
Derobert

@derobert, warum fragst du dich? Sie sehen Code so ziemlich oft ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;etc.
Matthias

@Matthias, weil die Zeile einen einzelnen Wert auswählen und speichern soll und statt eines Skalars in einem Array gespeichert wird.
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]);

Es nimmt immer Julie.

Es enthält eckige Klammern, und der Kommaoperator gibt den Wert seines rechten Operanden zurück.
Es ist auch sehr leicht zu übersehen. Ich habe es schon mal in echtem Code vermisst .


Das ist herrlich. Endlich eine Verwendung für diesen schrecklichen, schrecklichen Bediener.
Keen

5
Das Komma ist in diesem Zusammenhang eher ein Operator als ein Trennzeichen. ecma-international.org/ecma-262/5.1/#sec-11.14 Und es ist schrecklich. Es sei denn, Sie möchten, dass Ihr Code schwer zu lesen ist. Wie du es hier tust. Also, ein dickes Lob.
Keen

2
@Cory Ja, ich bin damit einverstanden - obwohl ich es die ganze Zeit für Code Golf mit Funktionsausdrücken (zB (a,b)=>(a=b[0],b)) benutze . Ich habe meine Antwort geklärt.
Zahnbürste

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]);
        }
    }
}

Der Trick ist, dass die Methode new Random().NextDouble()ein Double zwischen 0 und 1 zurückgibt. Wenn Sie Math.Floor()diesen Wert anwenden , ist er immer 0.


24
Es hielt meinem schnellen Blick nicht stand. ;)
Martin Ender

1
@TimS. so wie das? : P
Knerd

2
+1, viel besser - ich weiß, was Sie wirklich tun, aber es könnte jemanden täuschen, der mit der API nicht allzu vertraut ist.
Tim S.

1
Das weiß ich nicht. Wenn Sie einen var random = new Random(5); var id = random.NextInt(5);
Startwert angeben möchten

2
@clcto Meiner Meinung nach ist es bei zweimaligem Einbeziehen wahrscheinlicher, dass jemand zweimal nach dem Grund fragt und das Problem sieht. Das einmalige Einfügen von Code und das anschließende Einfügen von unnötigem Code führt zu einer gewissen Umleitung / Untätigkeit. Bonus: Wenn jemand einen der Fehler behebt, gibt es einen anderen.
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]);

Hinweis:

Startwert aus GUID generieren. Guids haben eine Kollisionswahrscheinlichkeit von 4 × 10−10. Super zufällig.

Antworten:

Zumindest wenn du benutzt Guid.NewGuid(), whoops! (Sneaky Weg, um Samen immer 0 zu machen). Auch sinnlos (int) für Fehlleitungen.


Die andere Art, wie ich das machen könnte, ist, AddRangedurcheinander zu kommen, Concatwenn ich Namen zu a hinzufüge List<string>. Mir ist der Gedanke gekommen, ein Hashset mit einem hinterhältigen IEqualityComparer zu haben, aber es wäre einfach viel zu ungewöhnlich. In meinem Kredit gab es nicht viele (wenn überhaupt) Samen-basierte Antworten, als ich dies gepostet habe.
Nathan Cooper

Ich nehme an, du hattest die gleiche Idee wie ich, aber du warst etwas schneller und es war etwas schwieriger zu sehen. +1!
Tsavinho

7
Das Setzen des Zufallszahlengenerators ist ein offensichtlicher Trick, aber Sie haben ihn hier hervorragend versteckt. Schöne Arbeit.
TRiG

18

Bash / Coreutils

Dies ist fast wörtlich aus einem Skript entnommen, das ich für einen ähnlichen Zweck geschrieben habe.

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

Selbst das Vergessen, ein R in Großbuchstaben zu schreiben, ist ein Fehler, den ich gelegentlich in echten Skripten gemacht habe.


3
könntest du eine bessere Erklärung geben? Ihre aktuelle Version ist sehr kurz und für jemanden, der sich mit Bash nicht wirklich auskennt, nicht hilfreich.
iFreilicht

6
-rGibt die umgekehrte (lexikografische) Sortierung an, sodass Steve immer ausgewählt wird. Es könnte als ein unschuldiger Tippfehler von gesehen werden-R für zufällige Sortierung angesehen werden
Max

3
Dies ist eine gute Erinnerung, nicht auf Kommentare zu vertrauen, sondern den Code sorgfältig zu lesen!
TecBrat

16

Rubin

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

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

Dies würde funktionieren richtig mit sort_by, abersort erwartet , dass eine Vergleichsfunktion , die wie funktioniert <=>. Das Ergebnis von rand () ist immer positiv, sodass es immer äquivalente Ergebnisse liefert, vorausgesetzt, der sortAlgorithmus Ihrer Ruby-Implementierung ist deterministisch. Mein Ruby 1.9.3 gibt immer Julie aus.


12

Rubin

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

puts names[rand() % 5]

rand() Ohne Argumente wird ein zufälliger Gleitkommawert zwischen 0 und 1 erzeugt. Modulo 5 führt also nichts aus, und wenn Ruby in ein Array mit einem Gleitkomma-Argument zerlegt, rundet es einfach ab, sodass dies immer John zurückgibt.


11

Perl

drei srands machen es dreimal zufälliger!

#!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!";

Erläuterung

In Perl gibt es kein $ RANDOM, sondern eine undefinierte Variable. Der Code gibt immer das erste Element aus der Liste zurück - Getränke auf John :)

bearbeiten:

Nachdem einer der fünf Entwickler den Code durchgearbeitet hat, hat er beschlossen, den offensichtlichen Fehler zu beheben, und das folgende Programm erstellt:

#!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!";

Kannst du sagen, wer es getan hat, indem du dir den Code ansiehst?

Erläuterung:

Gibt in Perl $#arrayden Index des letzten Elements zurück. da Arrays Null-Basis wird, einen Verweis auf ein Feld mit fünf Elementen gegeben $#$aref_peoplewerden 4.
randgibt eine Zufallszahl zurück, die größer oder gleich Null und kleiner als ihr Parameter ist, daher wird sie niemals zurückgegeben 4, was effektiv bedeutet, dass Julie niemals Getränke kauft :)


1
$RANDOMist ein echtes Feature in Bash, Ksh und Zsh (aber nicht in Perl).
Kernigh

10

Python

Jeder weiß, dass man in einem so kleinen Probenraum der Zufälligkeit nicht trauen kann; Um es wirklich zufällig zu machen, habe ich die veraltete Methode zum Auswählen eines Namens aus einer Liste aufgegeben. Stattdessen schreibt mein Programm einen vollständig zufälligen Namen. Da die meisten Namen im Büro 4 Buchstaben hatten, werden wir uns damit abfinden.

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)

Natürlich habe ich einige Vorbereitungsarbeiten durchgeführt, um sicherzustellen, dass ich den richtigen Samen auswähle.


15
Das Setzen der Zufallszahl, die mit einer Konstanten generiert wird, ist einfach zu offensichtlich.
Brendan Long,

@BrendanLong Es würde definitiv die Augenbrauen hochziehen. Die Leute würden es testen wollen, um sicherzugehen, dass es zufällig ist. Und wenn nicht, rate mal, wer Getränke kauft.
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] );
}

Entschuldigung, Jeff!

Nach ein paar Iterationen ist r == 1 mod 5, aus mathematischen Gründen. Moral: Schreiben Sie kein eigenes PRNG, wenn Sie schlecht in Mathe sind. :)


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;
}

Die Größe des Vektors ist aufgrund der in der Initialisierungsliste verwendeten Klammer 1. Der Kommaoperator verwirft alle Namen und gibt den letzten zurück, daher ist der Käufer immer Roy.


10

Scala

Ich weiß, dass meine Benutzer skeptisch sind, daher habe ich einen Beweis dafür beigelegt, dass meine Zufälligkeit wirklich fair ist!

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
  }

}

Ein Beispiellauf:

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

John kauft immer die Getränke, es sei denn, jemand anderes hat großes Glück.

Der "Beweis" der Zufälligkeit beruht auf der Tatsache, dass er rand(1, 4) * rand(1, 4) % 5immer noch gleichmäßig zwischen 1 und 4 einschließlich verteilt ist. Ist rand(1, 5) * rand(1, 5) % 6aber entartet. Es besteht die Möglichkeit, dass Sie eine 0 erhalten, die dann das Endergebnis 0 ergibt, unabhängig vom Rest der "Zufälligkeit".



9

JavaScript

Zweiter Versuch, dies ist ein bisschen kniffliger:

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

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

Die argumentsVariable ist für Funktionen lokal zugänglich und ein Array aller an die Funktion übergebenen Argumente. Indem Sie eine einfache Benennung verwenden und ein Array an die Funktion selbst übergeben, können Sie darauf hinweisen, dass nicht die Länge des Arrays, sondern die Länge der Argumentliste (1) verwendet wird. Dies kann noch besser ausgeführt werden, indem spezielle Zeichen oder eine Schriftart verwendet werden.


Dies war nicht das am schwersten zu erkennende. Jeder, der Nin JavaScript eine beliebige Funktion erstellt hat, kennt die argumentsVariable.
Conor O'Brien

8

C ++

Um fair zu sein, sollten wir viele, viele Versuche durchführen und auswählen, wer am häufigsten ausgewählt wird.

#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))]);
}

Was ist der Wert von 1<<31? Entschuldigung, John.


Die Antwort auf Ihre Spoilerfrage lautet UB. Ich bin unschlüssig, ob das besser oder schlechter ist.
NWP

@nwp Nun, sicher, aber es gilt überall, dass int das 32-Bit-2-Komplement ist, was auch auf 64-Bit (mit gcc) der Fall zu sein scheint. Ich habe es jedoch nicht mit Clang getestet.
flauschige

Nein, es gilt nirgendwo, wo ein Int 32 ist, sondern das Komplement von 2. Der Wert von 1 << 31 ist undefiniert. Sie haben Glück, undefiniertes Verhalten lässt den Compiler wählen, wie es sich anfühlt, und da es auf Geschwindigkeit ausgelegt ist, entscheidet er sich einfach dafür, nichts zu tun, was zufällig das ist, was Sie wollen.
NWP

@nwp 1<<31 == 0x80000000Egal was, genau definiert <<und im 32-Bit-2-Komplement, das ist es INT_MIN. Denken Sie vielleicht darüber nach, 1<<32welche vielleicht oder welche nicht == 0? (Weil auf x86, in der 1<<32Regel 1 auswertet ...)
flauschige

@nwp Es ist tatsächlich implementierungsdefiniert. Nun , wenn wir über C sprechen, dann wäre es nicht definiert sein.
Stuart Olsen

7

T-SQL (2008+)

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

Erläuterung:

In MS SQL Server wird RAND()nur einmal pro Ausführung ausgewertet. Jeder Name erhält immer die gleiche Nummer, so dass die ursprüngliche Bestellung erhalten bleibt. John ist der Erste. Saugt für John.

Verbesserungsvorschlag:

T-SQL kann ordentliche, zeilenweise Zufallszahlen mit erzeugen RAND(CHECKSUM(NEWID())).


Ich denke, ORDER BY NEWID () wird ausreichen (keine Notwendigkeit zu prüfen)
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()ist für Timing-Zwecke, os.time()ist das , was math.randomseedfür eine gute RNG verwendet werden sollte. Leider kauft Julie immer (zumindest auf meinem Computer).


math.random()Ohne Argumente wird auch eine Zahl im Bereich zurückgegeben [0,1). -1 für das nicht fangen.
16.

@mniip: Wirklich auch verdient! Ich habe es jetzt behoben.
Kyle Kanos

6

Idiomatisches C ++ 11

Wenn es um Getränke geht, ist es besonders wichtig, mit den neuesten Standards und Codierungsstilen auf dem Laufenden zu sein. Dies ist ein großartiges Beispiel für eine hocheffiziente und idiomkompatible C ++ 11-Namensauswahl.

Es wird von der Systemuhr geimpft und gibt den Startwert zusammen mit dem Namen jedes Mal zur Überprüfung aus.

#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
}

Versuchen Sie dies live: http://ideone.com/KOet5H

Ok, das ist eigentlich ein ziemlich guter Code. es gibt eine Menge von falschen Fährten Sie schauen zu dicht auf dem Code , um das Offensichtliche zu bemerken - , dass die RNG eigentlich nie :) ausgesät in diesem Fall seednur eine ganze Zahl ist, und während es sieht aus wie engineals Parameter an einem übergeben wird Seeding-Funktion, es ist eigentlich nur ignoriert. Die Saatvariable wird wirklich von der Uhr aus eingestellt, sodass sie am Ende zusammen mit dem Namen ausgegeben werden kann, um die Verletzung zu beleidigen, aber es wird immer Steve sein, der die Getränke kauft.


1
Es bringt mich um, dass es keine Initialisierungsliste für die Namen verwendet. Zumindest ist es Ihnen definitiv gelungen, Code bereitzustellen , der sich nur überentwickelt anfühlt . Ich kann nicht sagen, ob es an der "Compliance" liegt oder an allen Geräuschkommentaren: P
vmrob

6

JavaScript

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

Tut mir leid, Math.randomnimmt keinen Parameter und gibt immer eine Zahl von [0, 1) zurück. Trotzdem ist es eine glückliche Variadic-Funktion und beschwert sich nicht über Argumente!


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) ergibt eine konstante Zeichenkette; kein zufälliger Wert


6
Ein etwas irrelevanter Hinweis: Wenn Sie 3.2 mit Python sind oder später, das zweite Argument zu random.seed()müssen 2(die Standardeinstellung). Wenn Sie übergeben version=1, wird der hash()von der Zeichenfolge als Startwert anstelle der gesamten Zeichenfolge verwendet, und da Python die Hashwerte der Zeichenfolgen ab 3.2 zufällig einsetzt, erhalten Sie einen tatsächlich zufälligen Namen.
Blacklight Shining

5

Perl

Emma sollte ihren Geldbeutel besser nicht vergessen! Läuft unter strictund 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.

Erklärung hier .


Perl 5.18 hat dies ein wenig geändert, indem Hash-Schlüssel-Randomisierung eingeführt wurde (um Angriffe auf die Komplexität von Hash-Kollisionen zu vermeiden).
Konrad Borowski

4

JavaScript

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

Das |0Ergebnis ist die ganze Zeit 0, sieht aber so aus, als würde es eine andere Rundung machen.


Ich mag das. Obwohl ich parseInt(Math.random(0, 4))Kommentare wie "- Math.randomreturn a double" machen und vielleicht hinzufügen würde , konvertieren Sie diese zuerst in eine Ganzzahl
Claudiu

5
Der Trick ist eigentlich, dass Math.randomsich nichts für unsere mageren Parameter interessiert. Es wählt die Zahlen auf seine Weise. das |0ist das unerwartete Ergebnis korrekt Rundung, und so ist keine Quelle eines trickery.
Keen

|0ist für einige sehr offensichtlich (wahrscheinlich für uns alle), aber ich wette, es gibt eine Menge, die keine Ahnung haben, was es tut. Das ist die Gruppe, auf die ich mich verlassen habe.
Matt

3
@Matt Ich meine |0, wenn du weißt, was es tut, sieht es so aus, als würde es abrunden, und es wird abgerundet, also ist es keine Täuschung. (Und wenn jemand keine Ahnung hat , was der |0Fall ist, dann gibt es keine Verwendung für trügerisch Code;. Sie kann nur sagen , was Sie wollen , dass sie glauben) Stattdessen das unerwartete Verhalten in Ihrer Antwort beruht auf der Tatsache , dass Math.random(0,4)zu funktional identisch ist Math.random(), weil Math.randomverwendet keine Parameter.
Keen

4

J

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

Die arme Julie ... Trivia: Das war vielleicht das sauberste J, das ich je geschrieben habe ...

Dieser Code ist bis auf eines richtig. ?.is the uniform rng: ?.5wird immer zurückkehren 4. ?5wäre richtig gewesen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.