Losowy skrypt, który tak naprawdę nie jest losowy

106

Jako mały żart w biurze ktoś chciał skryptu, który losowo wybiera nazwisko, i powiedział, że ktoś zrobi drinka.

Nazwijmy ludzi John, Jeff, Emma, ​​Steve i Julie.

Pomyślałem, że fajnie byłoby stworzyć skrypt, który na pierwszy rzut oka wydaje się losowy, ale w rzeczywistości zawsze daje tę samą osobę co wynik (do ciebie, kogo wybierzesz).

Najwyżej głosowana odpowiedź wygrywa po tygodniu

A zwycięzcą jest....

Paul R z (obecnie) 158 głosami.

Odpowiedzi tutaj są świetne, a jeśli ktoś ma jeszcze jakieś pomysły, które nie zostały jeszcze opublikowane, dodaj je, uwielbiam je czytać.

TMH
źródło
44
xkcd.com/221
AstroCB
6
@AstroCB jeden z moich ulubionych. Tuż za stołami bobby.
Cruncher
50
Wygląda na to, że bardziej przypadkowa byłaby losowość, z wyjątkiem tego, że nigdy nie wybrała jednej osoby.
Brendan Long,
6
@AstroCB ten jest również fantastyczny: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb
3
Przeszedłem przez pierwszą stronę: większość odpowiedzi zawsze wybiera Johna, 2. najwyższa to Julie, Jeff jest wybierany rzadko, a Steve o 1. Nawet Ray został wybrany przez jednego, ale nikt nie wybrał Emmy. Morał tej historii: stojąc w szeregu i losowo decydując, kto kupi napoje, nazwij się Emma.
Nędzna Zmienna

Odpowiedzi:

171

do

Ważne jest, aby zdecydować, kto kupuje tak szybko, jak to możliwe, aby nie marnować cennego czasu na picie - dlatego C jest oczywistym wyborem, aby uzyskać maksymalną wydajność:

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

Wyjaśnienie:

To działałoby dobrze, gdyby break;w instrukcji switch znajdował się po każdym przypadku. Na razie jednak „przypadek” przechodzi do następnego, więc biedna Julie zawsze kupuje napoje.

Paul R.
źródło
17
+1 za wydajność - znacznie szybciej niż rzucenie fizyczną kostką! ;)
Jwosty
16
Zastanawiam się nad dalszą optymalizacją, być może za pomocą SIMD lub GPGPU, aby uzyskać nieco większą wydajność. ;-)
Paul R
7
Obowiązuje absolutnie prawdziwy koncert. Nikt nawet nie kwestionowałby, że był to wypadek.
iFreilicht,
5
Czy to tylko ja, czy jest to zbyt oczywiste, aby je dostrzec?
Alvin Wong
3
@AlvinWong Nie zauważyłem tego od razu. Z drugiej strony nie używam C regularnie ani żadnego innego języka, który pochodzi z BCPL.
Rhymoid
164

PHP

Nie mogłem odpuścić, więc oto kolejny:

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

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

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

W rzeczywistości nie jest to gwarantowane, aby produkować Johna, ale szanse są bardzo dobre. PHP chętnie weźmie wszystko, co / dev / random ma do zaoferowania, aby zobaczyć, że (prawdopodobnie) nie może go przeanalizować i zamiast tego wymyśli bardzo rozsądną liczbę 0. W końcu powiadomienie programisty o potencjalnym błędzie jest uważane za śmiertelny grzech w PHP.

monokomórka
źródło
25
Musisz pokochać PHP - a nawet lepiej, czasami rzadko wybierze kogoś innego. Więc jeśli masz szczęście, na początku będzie to trochę stronnicze
Falco
142
+1000 za „... powiadomienie programisty o potencjalnym błędzie jest uważane za śmiertelny grzech w PHP.”
jsedano
85

Haskell

Jest zbyt przezroczysty, jeśli zawsze zwraca tę samą nazwę, więc spróbuj wykonać następujące czynności

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

Ilekroć chcesz, aby był losowy:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

A dla twojego niefortunnego celu:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

Uściski implementują tylko wielozadaniowość kooperacyjną, więc rotatewątek nigdy się nie uruchomi

monokomórka
źródło
24
To diabelskie!
Daenyth,
8
Czujesz się jak fotografowanie kości, które jeszcze nie przestały się poruszać.
Vi.
1
@Vi. To ładna analogia. Na szczęście użycie MVars gwarantuje, że obraz nie będzie rozmazany. :)
monocell
@monocell Cóż, technicznie rzecz biorąc, nawet zdjęcie poruszającego się obiektu może być wyraźne.
ghosts_in_the_code
75

Bash - maksymalna prostota

Bardzo prosty przykład - unikajmy problemów, robiąc to w sposób podręcznikowy. Nie zapomnij zaszczepić generatora z zegara systemowego, aby uzyskać dobry wynik!

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

Zależy to od tego, czy użytkownik nie wie, co $SECONDSwłaściwie robi wbudowane narzędzie; zwraca liczbę sekund od uruchomienia bieżącej powłoki. Jak jest w skrypcie, powłoka zawsze zaczynała się zero sekund temu, więc generator jest zawsze zaszczepiony, 0a Julie zawsze kupuje piwo.

Premia:

Ten dość dobrze radzi sobie z badaniem; Jeśli wpiszesz ten sam kod w wierszu poleceń zamiast w skrypcie, da on losowe wyniki, ponieważ $SECONDSzwróci czas działania interaktywnej powłoki użytkownika.

Zamieszki
źródło
9
\ o / Mean !!! Prawdziwe znaczenie!!! $SECONDSftw! \ o /
yeti
Co się stanie, jeśli sourceto zrobisz , zamiast po prostu wykonać? Czy shebang nadal wyzwala nową powłokę czy coś takiego?
jpmc26
1
@ jpmc26: jeśli wykonasz go, sourceto jest dokładnie tak samo, jakbyś sam wpisał polecenia w wierszu poleceń; #! / bin / bash jest komentarzem, więc jest ignorowany. Dotyczy to każdego skryptu.
Riot
57

DO#

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

Może to nie zmylić osób zaznajomionych z interfejsem API .Net, ale osoby, które go nie znają, mogą wierzyć, że OrderBymodyfikują obiekt, do którego go wywołujesz, i jest to prawdopodobny błąd dla nowicjuszy interfejsu API.

Peter Taylor
źródło
1
Nawet jeśli OrderBy hipotetycznie zmodyfikuje obiekt, czy to wywołanie faktycznie posortuje listę losowo? Jako ktoś, kto nie zna platformy .NET, zgaduję, że ponieważ rng.Next()jest wywoływana tylko raz, tablica będzie sortowana według stałej, co nie spowoduje żadnej zmiany (lub zmiany, która zależy tylko od algorytmu sortowania).
Brilliand
1
@Brilliand Argument przekazany do OrderBy nie jest wartością statyczną, jest wykonywany za każdym razem, gdy element jest sortowany, iw tym przypadku zwraca losowe wartości bez porównywania żadnych wartości. Właściwie działałoby to poprawnie, gdyby linia tonames = names.OrderBy(name => rng.Next());
user3188175
1
=>Wskazuje, że jest to N wyrażenie C # (zamknięcie).
Snowbody
44

PowerShell

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

To zawsze wyjdzie John.

$namesto taki, System.Collections.Hashtablektóry nie ma Lengthwłaściwości. Począwszy od programu PowerShell v3 Length(i również Count) można go użyć jako właściwości dowolnego obiektu. Jeśli obiekt nie ma właściwości, zwróci, 1gdy obiekt nie będzie miał wartości null, w przeciwnym razie zwróci 0. Tak więc w mojej odpowiedzi $names.Lengthocenia się jako 1 i random -maximum 1zawsze zwraca 0, ponieważ maksimum jest wyłączne.

Rynant
źródło
42

Q

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

Q zawsze inicjuje ziarno liczby losowej o tej samej wartości.

skeevey
źródło
8
więc w zasadzie nie jest to przypadek
Sam Creamer
3
@SamCreamer Celem tego pytania jest, aby wynik był nieprzypadkowy. Ale to wygląda losowo, więc zdecydowanie pasuje do ustawy
Cruncher
4
Przepraszam, miałem na myśli, że losowe liczby Q nie są tak losowe, to pytanie z pewnością spełnia kryteria. Nie chciałem spotkać się w ten sposób!
Sam Creamer,
Tak, więc musisz znaleźć swój własny sposób na generowanie losowego ziarna za każdym razem, gdy chcesz użyć randa? Brzmi ... użytecznie.
DLeh
1
Może bardzo łatwo ustawić losowe ziarno ręcznie ... uruchomić tłumacza z -S 1234opcją lub zrobić \S 1234z interpretera
skeevey
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";

Wydruki: Person X is buying: Jeff(gdzie X jest od 0-4)

Trochę nadużywa kontekstu skalarnego. @index = int(rand() * 5)umieszcza losową liczbę całkowitą od 0 do 4 na 0 pozycji @indexlisty. Podczas drukowania tablicy poprawnie drukuje losową liczbę całkowitą w @index, ale przy użyciu jako indeksu tablicy w $people[@index]@index używa kontekstu skalarnego, nadając mu wartość wielkości listy, tj 1.

Co ciekawe, @people[@index]sprawia, że ​​indeks jest poprawnie.

Co ciekawe, @people[@index]w Perlu jest wystarczający plasterek, więc @indexjest oceniany w kontekście listy; w tym przypadku jest to lista pojedynczych wpisów i dlatego działa poprawnie

Allen G.
źródło
Więc w kategoriach C (++) zachodzi niejawna konwersja z listy na skalar, ponieważ podczas indeksowania oczekiwany jest skalar?
iFreilicht
@iFreilicht Prawidłowo. W Perlu wyrażenia mogą być oceniane jako lista lub jako skalar, w zależności od tego, gdzie się pojawiają. W rezultacie to samo wyrażenie może oznaczać różne rzeczy, w zależności od kontekstu. Zmienna listy (tj. Zmienna z @prefiksem) w „kontekście listy” jest interpretowana jako wszystkie jej elementy, ale w „kontekście skalarnym” jest skalarem równym całkowitej liczbie elementów na liście. Dlatego wewnątrz łańcucha zmienna listy ma kontekst listy i zostaje interpolowana, i otrzymujemy Person X is buying. Ale jako indeks tablicowy otrzymuje kontekst skalarny i jest interpretowany jako 1.
Allen G
3
Problem polega na tym, że gdy programista Perla widzi my @index = ..., natychmiast zastanawia się „WTF ?!”.
derobert
@derobert, dlaczego miałbyś się zastanawiać? Często widzisz taki kod ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;itd.
Matthias
@Matthias, ponieważ linia ma pobierać i przechowywać pojedynczą wartość, a zamiast skalara jest przechowywana w tablicy.
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]);

To zawsze podnosi Julie.

Ma nawiasy kwadratowe, a przecinek operator zwraca wartość swojego prawego operandu.
Bardzo łatwo go przeoczyć. Wcześniej tęskniłem za prawdziwym kodem.

Szczoteczka do zębów
źródło
To jest zachwycające. Wreszcie zastosowanie dla tego okropnego, okropnego operatora.
Keen
5
Przecinek w tym kontekście jest technicznie operatorem, a nie separatorem. ecma-international.org/ecma-262/5.1/#sec-11.14 I to jest okropne. Chyba że chcesz, aby Twój kod był trudny do odczytania. Tak jak tutaj robisz. Cześć.
Keen
2
@Cory Tak, zgadzam się - chociaż używam go cały czas dla Code Golf z wyrażeniami funkcyjnymi (np (a,b)=>(a=b[0],b).). Wyjaśniłem swoją odpowiedź.
Szczoteczka do zębów
21

DO#

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

Sztuczka polega na tym, że metoda new Random().NextDouble()zwraca podwójną wartość od 0 do 1. Po zastosowaniu Math.Floor()tej wartości zawsze będzie to 0.

Knerd
źródło
24
Nie wytrzymało mojego szybkiego spojrzenia. ;)
Martin Ender
1
@TimS. tak? : P
Knerd
2
+1, Znacznie lepiej - wiem, co naprawdę robisz, ale może oszukać kogoś, kto nie jest zbyt obeznany z interfejsem API.
Tim S.
1
Nie wiem o tym Jeśli zamierzasz podać ziarno, dlaczego nie użyć właściwego sposobu uzyskania „losowego” int:var random = new Random(5); var id = random.NextInt(5);
clcto
2
@clcto Moim zdaniem, dwukrotne włączenie tej opcji może skłonić kogoś do podwójnego ujęcia, zapytaj dlaczego i zobacz problem. Włączenie go raz, a następnie dołączenie niepotrzebnego kodu, daje trochę przekierowania / niedostosowania. Bonus: jeśli ktoś naprawi jeden z błędów, inny istnieje.
Tim S.
18

DO#

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

Wskazówka:

Wygeneruj seed z GUID. Prowadnice mają szansę na kolizję 4 × 10–10. Super losowy.

Odpowiedź:

Przynajmniej kiedy używasz Guid.NewGuid(), ups! (Podstępny sposób na zrobienie nasion zawsze 0). Również bezcelowe (int) dla błędnego przekierowania.

Nathan Cooper
źródło
Innym sposobem, w jaki mogę to zrobić, jest AddRangezagubienie się Concatpodczas dodawania nazw do List<string>. Przyszło mi do głowy, że mam zestaw Hashset ze sprytnym IEqualityComparer, ale byłoby to po prostu zbyt niezwykłe. Na moim koncie nie było wielu (jeśli w ogóle) odpowiedzi opartych na ziarnach, kiedy to opublikowałem.
Nathan Cooper
Domyślam się, że miałeś taki sam pomysł jak ja, ale byłeś trochę szybszy i utrudniałeś dostrzeżenie. +1!
tsavinho
7
Rozsiewanie generatora liczb losowych jest oczywistą sztuczką, ale tutaj świetnie go ukryłeś. Cudowna robota.
TRiG
18

bash / coreutils

Zostało to zaczerpnięte niemal dosłownie ze skryptu, który napisałem w podobnym celu.

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

Nawet zapominanie o użyciu dużej litery R jest błędem, który czasami popełniam w skryptach z prawdziwego życia.

kasperd
źródło
3
czy możesz podać lepsze wyjaśnienie? Twój obecny jest naprawdę krótki i nie jest pomocny dla kogoś, kto tak naprawdę nie zna bash.
iFreilicht
6
-rokreśla sort odwrotny (leksykograficzny), więc Steve zawsze zostanie wybrany. Może to być postrzegane jako niewinna literówka -Rdla losowego sortowania
Max
3
To dobre przypomnienie, aby nie ufać komentarzom, ale uważnie przeczytać kod!
TecBrat
16

Rubin

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

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

Działa to poprawnie sort_by, ale sortoczekuje, że działa funkcja porównania <=>. Wynik rand () zawsze będzie dodatni, więc zawsze będzie generował równoważne wyniki, pod warunkiem, że sortalgorytm twojej implementacji Ruby jest deterministyczny. Mój Ruby 1.9.3 zawsze wyświetla Julie.

histocrat
źródło
12

Rubin

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

puts names[rand() % 5]

rand() bez argumentów tworzy losową liczbę zmiennoprzecinkową od 0 do 1. Tak więc modulo 5 nic nie robi, a podczas krojenia w tablicę z argumentem zmiennoprzecinkowym Ruby zaokrągla ją w dół, więc zawsze zwraca John.

histocrat
źródło
11

Perl

trzy srands sprawią, że będzie trzy razy bardziej losowy!

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

wyjaśnienie

w perlu nie ma $ RANDOM, jest to niezdefiniowana zmienna. kod zawsze zwróci pierwszy element z listy - napoje na Johnie :)

edytować:

po przejrzeniu kodu jeden z pięciu gości postanowił naprawić oczywisty błąd, tworząc następujący program:

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

czy możesz powiedzieć, kto to zrobił, patrząc na kod?

wyjaśnienie:

w Perlu $#arrayzwraca indeks ostatniego elementu; ponieważ tablice są zerowe, odniesienie do tablicy z pięcioma elementami $#$aref_peoplebędzie 4.
randzwraca liczbę losową większą lub równą zero i mniejszą niż jej parametr, więc nigdy nie zwróci 4, co w rzeczywistości oznacza, że ​​Julie nigdy nie kupi napojów :)

goth chiński perl
źródło
1
$RANDOMjest prawdziwą funkcją w bash, ksh i zsh (ale nie w perlu).
kernigh
10

Pyton

Wszyscy wiedzą, że nie można ufać przypadkowości w tak małej próbce; aby było naprawdę losowe, zrezygnowałem z przestarzałej metody wybierania nazwy z listy, a zamiast tego mój program wypisze całkowicie losową nazwę. Ponieważ większość nazwisk w biurze ma 4 litery, zadowolimy się tym.

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)

Oczywiście wykonałem pewne prace przygotowawcze, aby upewnić się, że wybrałem właściwe ziarno.

Tal
źródło
15
Zaszczepienie generowanej liczby losowej stałą jest zbyt oczywiste.
Brendan Long
@BrendanLong To zdecydowanie podniosłoby brwi. Ludzie chcieliby go przetestować, aby upewnić się, że jest losowy. A jeśli nie, zgadnij, kto kupuje napoje.
JFA
10

do

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

Przepraszam, Jeff!

Po kilku iteracjach r == 1 mod 5 z powodu matematyki. Moralność: nie pisz własnego PRNG, jeśli jesteś kiepski z matematyki. :)

CPRI
źródło
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;
}

Rozmiar wektora wynosi w rzeczywistości 1 ze względu na nawiasy użyte na liście inicjalizatora. Operator przecinka odrzuci wszystkie nazwiska i zwróci ostatnie, dlatego nabywcą jest zawsze Roy.

tomasz
źródło
10

Scala

Wiem, że moi użytkownicy będą sceptyczni, dlatego dołączyłem dowód, że moja losowość jest naprawdę sprawiedliwa!

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
  }

}

Jeden przykładowy przebieg:

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

O ile ktoś nie będzie miał szczęścia, John zawsze kupuje napoje.

„Dowód” losowości polega na tym, że rand(1, 4) * rand(1, 4) % 5nadal jest równomiernie rozłożony między 1 a 4 włącznie. Ale rand(1, 5) * rand(1, 5) % 6jest zdegenerowany. Istnieje możliwość uzyskania 0, co w efekcie dałoby wynik końcowy 0 niezależnie od reszty „losowości”.

Joe K
źródło
10

JavaScript (z Underscore.js )

Ponieważ javascript nie ma wbudowanego odtwarzania losowego, będziemy używać Underscore.js

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

_.shuffle zwraca przetasowaną tablicę, nie zmienia się ona jako Array.prototype.sort () , przepraszam John

Kristoffer Sall-Storgaard
źródło
9

JavaScript

Druga próba, ta jest trochę trudniejsza:

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

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

argumentsZmienna jest dostępny lokalnie dla funkcji i jest tablicą wszystkich argumentów przekazywanych do funkcji. Używając prostej nazewnictwa i przekazując tablicę do samej funkcji, możesz sfałszować, że nie bierzemy długości tablicy, ale w rzeczywistości długości listy argumentów (która wynosi 1). Można to jeszcze lepiej wykonać za pomocą specjalnych znaków lub typu czcionki.

Thomaux
źródło
Nie było to najtrudniejsze do wykrycia. Każdy, kto skonstruował dowolną Nfunkcję-JavaScript w JavaScript, wie o argumentszmiennej.
Conor O'Brien
8

C ++

Aby być uczciwym, powinniśmy przeprowadzić wiele, wiele prób i wybrać tego, który jest najczęściej wybierany.

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

Jaka jest wartość 1<<31? Przepraszam, John.

puszysty
źródło
Odpowiedź na twoje pytanie dotyczące spoilera to UB. Nie jestem zdecydowany, czy to sprawia, że ​​jest lepiej, czy gorzej.
nwp
@nwp Cóż, jasne, ale zachowuje wszędzie tam, gdzie int jest uzupełnieniem 32-bit 2, co wydaje się, że dzieje się tak nawet w 64-bit (z gcc). Jednak nie testowałem na Clangu.
puszysty
Nie, nie ma to gdziekolwiek int, który jest 32-ale uzupełnieniem 2. Wartość 1 << 31 jest niezdefiniowana. Masz jednak szczęście, nieokreślone zachowanie sprawia, że ​​kompilator wybiera to, co czuje, a ponieważ jest stworzony z myślą o szybkości, po prostu zdecyduje się nic nie robić, co jest tym, czego chcesz.
nwp
@ nwp 1<<31 == 0x80000000bez względu na to, co z samej definicji <<i na 32-bitowym uzupełnieniu 2, to jest to INT_MIN. Zastanawiasz się, 1<<32który z nich może, a nie może == 0? (Ponieważ na x86 1<<32zwykle ocenia się na 1 ...)
puszysty
@nwp W rzeczywistości jest on zdefiniowany w implementacji. Teraz, gdy mówiliśmy o C, wtedy byłoby niezdefiniowany.
Stuart Olsen
7

T-SQL (2008+)

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

Wyjaśnienie:

W MS SQL Server RAND()ocenia tylko raz na wykonanie. Każde imię ma zawsze przypisany ten sam numer, pozostawiając oryginalne zamówienie. John jest pierwszy. Bani dla Johna.

Sugerowana poprawa:

T-SQL może generować przyzwoite jakości losowe liczby w wierszu RAND(CHECKSUM(NEWID())).

comfortlydrei
źródło
Myślę, że wystarczy ORDER BY NEWID () (nie trzeba KONTROLI)
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()służy do pomiaru czasu, os.time()to jest to , co powinno być używane math.randomseeddo dobrego RNG. Niestety Julie zawsze kupuje (przynajmniej na moim komputerze).

Kyle Kanos
źródło
math.random()bez argumentów zwraca także liczbę z zakresu [0,1). -1 za nie złapanie tego.
mniip
@mniip: Naprawdę też na to zasłużyłem! Naprawiłem to teraz.
Kyle Kanos
6

Idiomatic C ++ 11

Gdy chodzi o napoje, szczególnie ważne jest, aby być na bieżąco z najnowszymi standardami i stylami kodowania; jest to świetny przykład bardzo wydajnego i zgodnego z idiomem selektora nazw C ++ 11.

Jest on wysyłany z zegara systemowego i za każdym razem wysyła nasiona wraz z nazwą do weryfikacji.

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

Wypróbuj to na żywo: http://ideone.com/KOet5H

Ok, więc ogólnie jest to całkiem niezły kod; jest wiele czerwonych śledzi, które sprawiają, że zbyt uważnie patrzysz na kod, aby zauważyć oczywiste - że RNG nigdy nie jest faktycznie zaszczepiony :) W tym przypadku seedjest to tylko liczba całkowita i chociaż wygląda na to, że enginejest przekazywana jako parametr do parametru funkcja wysiewania, w rzeczywistości jest po prostu ignorowana. Zmienna nasion naprawdę jest ustawiana na podstawie zegara, więc może być wyprowadzana na końcu wraz z nazwą, aby dodać obrażenia do obrażeń, ale wciąż to Steve kupuje napoje.

Zamieszki
źródło
1
Zabija mnie to, że nie używa listy inicjalizacyjnej dla nazw. Przynajmniej na pewno udało ci się dostarczyć kod, który wydaje się zbyt zawężony. Nie umiem powiedzieć, czy to z powodu „zgodności”, czy wszystkich komentarzy na temat hałasu: P
vmrob
6

JavaScript

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

Przykro nam, Math.randomnie przyjmuje parametru i zawsze zwraca liczbę z [0, 1). Mimo to jest to szczęśliwa funkcja variadyczna i nie narzeka na argumenty!

Bergi
źródło
5

Pyton

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 (losowy) daje stały ciąg; nie losowa wartość

QuadrExAtt
źródło
6
Nieistotna uwaga: jeśli używasz języka Python 3.2 lub nowszego, drugim argumentem random.seed()musi być 2(domyślnie). Jeśli zdasz version=1, hash()łańcuch zostanie użyty jako ziarno zamiast całego łańcucha, a ponieważ Python losowo inicjuje wartości skrótu łańcuchów począwszy od 3.2, otrzymasz faktycznie losową nazwę.
Blacklight Shining
5

Perl

Emma nie powinna zapomnieć o swojej torebce! Działa pod stricti 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.

Wyjaśnienie tutaj .

Zaid
źródło
Perl 5.18 nieco to zmienił, wprowadzając randomizację klucza skrótu (aby uniknąć ataków na złożoność kolizji skrótu).
Konrad Borowski
4

JavaScript

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

Te |0wyniki w 0 cały czas, ale wygląda to robi jakąś inną zaokrąglenia.

Matt
źródło
Lubię to. Chociaż zrobiłbym to parseInt(Math.random(0, 4))i może dodam komentarze w stylu - Math.randomzwraca wartość podwójną, więc najpierw przekonwertuj ją na liczbę całkowitą
Claudiu
5
Sztuczka polega na tym, że Math.randomnic nie obchodzi naszych skromnych parametrów. Wybiera liczby na swój własny sposób. |0jest poprawnie zaokrąglania nieoczekiwany wynik, a więc nie jest źródłem jakiegokolwiek oszustwa.
Keen
|0jest to oczywiste dla niektórych (najprawdopodobniej dla nas wszystkich), ale założę się, że wielu nie ma pojęcia, co robi. To grupa, na której polegałem.
Matt
3
@Matt To znaczy, że |0jeśli wiesz, co robi, wygląda to zaokrąglenie w dół, i to jest zaokrąglenie w dół, więc nie jest to oszustwo. (A jeśli ktoś nie ma pojęcia, co |0robi, to nie ma sensu oszukiwać kodu; możesz po prostu powiedzieć mu, w co chcesz, aby uwierzył.) Zamiast tego, nieoczekiwane zachowanie w odpowiedzi opiera się na fakcie, że Math.random(0,4)jest funkcjonalnie identyczny z Math.random(), ponieważ Math.randomnie używa parametrów.
Keen
4

jot

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

Biedna Julie ... Ciekawostki: to mógł być najczystszy J, jaki kiedykolwiek napisałem ...

Ten kod jest właściwie poprawny, z wyjątkiem jednej rzeczy. ?.jest jednolity rng: ?.5zawsze zwróci 4. ?5byłoby poprawne.

.ıʇǝɥʇuʎs
źródło