Випадковий сценарій, який насправді не є випадковим


106

Як маленький жарт в офісі, хтось захотів сценарій, який випадковим чином вибирає ім’я, і сказана людина зробить випивку.

Давайте назвемо людей Джона, Джеффа, Емми, Стіва та Джулі.

Я думав, що було б смішно зробити сценарій, який здається випадковим на швидкому погляді, але насправді завжди дає ту саму людину, що і результат (Ви, кого ви обираєте).

Найвищий проголосований відповідь виграє через тиждень

А переможець -….

Пол Р. (наразі) 158 голосів.

Відповіді тут чудові, і якщо хтось ще має інші ідеї, які ще не були опубліковані, додайте їх, я люблю їх читати.



6
@AstroCB - один із моїх улюблених. Прямо за столами бобі.
Cruncher

50
Здається, це було б крихітніше, якби воно було випадковим, за винятком того, що ніколи не вибирати одну людину.
Брендан Довгий

6
@AstroCB це один також фантастичний: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb

3
Я переглянув першу сторінку: більшість відповідей завжди вибирають Джона, 2-ю вищу - Джулі, Джеффа вибирають рідко, а Стіва - 1. Навіть Рея вибрав один, але Емму ніхто не вибрав. Мораль історії: стоячи в черзі, щоб випадково вирішити, хто купуватиме напої, назвіть себе Еммою.
Жалюгідна змінна

Відповіді:


171

С

Важливо вирішити, хто купує якомога швидше, щоб не витрачати дорогоцінний питний час - отже, C - це очевидний вибір для отримання максимальної продуктивності:

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

Пояснення:

Це спрацювало б добре, якби break;після кожного випадку в операторі перемикання було після. Однак, однак, кожен випадок "проникає" до наступного, тому бідна Джулі завжди закінчує купувати напої.


17
+1 для продуктивності - набагато швидше, ніж катання фізичної штанги! ;)
Jwosty

16
Я думаю про подальшу оптимізацію, можливо, за допомогою SIMD або GPGPU, просто для того, щоб отримати трохи більше продуктивності. ;-)
Пол Р

7
Абсолютно реально застосовні в реальному часі. Ніхто ніколи навіть не сумнівався б у тому, що це випадковість.
iFreilicht

5
Це тільки я чи це занадто очевидно, щоб помітити?
Елвін Вонг

3
@AlvinWong Я не помітив цього відразу. Потім я знову не використовую C регулярно або будь-якою іншою мовою, що походить від BCPL.
Римоїд

164

PHP

Не можна цього відпустити, ось ось ще один:

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

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

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

Це насправді не гарантує виробництва Джона, але шанси дуже хороші. PHP з радістю візьме все, що / dev / random може запропонувати, побачивши, що він (ймовірно) не може його розібрати, і придумає дуже розумне число 0. Зрештою, попередження програміста про потенційну помилку вважається смертельним гріхом у PHP.


25
Ви повинні полюбити PHP - а ще краще, іноді рідко вибиратимуть когось іншого. Тож якщо вам пощастить, то спочатку це здасться трохи упередженим
Falco

142
+1000 за "... попередження програміста про потенційну помилку вважається смертельним гріхом у PHP."
jsedano


85

Хаскелл

Це занадто прозоро, якщо він завжди повертає те саме ім'я, тому спробуйте наступне

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

Щоразу, коли ви хочете, щоб це було випадковим чином:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

І для вашої нещасної цілі:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

Hugs реалізує лише кооперативний багатозадачність, тому rotateнитка ніколи не запускається


24
Це дьявольське!
Даеніт

8
Схоже, фотографувати кістки, які ще не перестали рухатися.
Ві.

1
@Vi. Це приємна аналогія. На щастя, використання MVars гарантує, що зображення не буде розмитим. :)
monocell

@monocell Ну, технічно, навіть фотографії об'єкта, що рухається, можуть бути зрозумілими.
ghosts_in_the_code

75

Bash - максимальна простота

Дуже простий приклад - давайте уникати будь-яких проблем, роблячи це підручником способом. Не забудьте посадити генератор з системного годинника для хорошого результату!

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

Це покладається на те, що користувач не знає, що $SECONDSнасправді робить вбудований; він повертає кількість секунд з моменту запуску поточної оболонки. Як і в сценарії, оболонка завжди запускалася нульові секунди тому, тому генератор завжди засіяний, 0а Джулі завжди купує пиво.

Бонус:

Цей досить добре розглядається; Якщо ви введете той самий код у командному рядку замість сценарію, він дасть випадкові результати, оскільки $SECONDSповерне тривалість часу, коли інтерактивна оболонка користувача працювала.


9
\ о / середній !!! Дійсно означає !!! $SECONDSftw! \ o /
yeti

Що станеться, якщо ти sourceце, а не просто виконати? Чи все-таки шебанг запустить нову оболонку чи щось таке?
jpmc26

1
@ jpmc26: якщо ви виконаєте його, sourceтоді це точно так само, як якщо б ви самі ввели команди в командному рядку; #! / bin / bash - це коментар, тому його ігнорують. Це стосується будь-якого сценарію.
Бунт

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

Це може не обдурити людей, які знайомі з API .Net, але люди, які його не знають, можуть повірити, що це OrderByзмінює об’єкт, на який ви його викликаєте, і це правдоподібна помилка для новачка в API, який він може зробити.


1
Навіть якби OrderBy гіпотетично змінив об'єкт, чи буде цей виклик насправді сортувати список випадковим чином? Як хтось незнайомий з .NET, моя перша здогадка полягала в тому, що оскільки він rng.Next()викликається лише один раз, масив буде відсортований за допомогою константи, що не призведе до зміни (або зміни, що залежить тільки від алгоритму сортування).
Brilliand

1
@Brilliand Аргумент, переданий OrderBy, не є статичним значенням, він виконується кожного разу, коли елемент сортується, і в цьому випадку повертає випадкові значення, не порівнюючи жодних значень. Насправді це буде правильно, якби лінія булаnames = names.OrderBy(name => rng.Next());
user3188175

1
=>Вказує на те, що це лямбда - вираз в C # (закриття).
Snowbody

44

PowerShell

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

Це завжди буде результатом John.

$names- це System.Collections.Hashtableне має Lengthвластивості. Починаючи з PowerShell v3, Length(і також Count) можна використовувати як властивість на будь-якому об’єкті. Якщо об’єкт не має властивості, він повернеться, 1коли об’єкт недійсний, інакше він повернеться 0. Тож у моїй відповіді $names.Lengthоцінюється як 1, і random -maximum 1завжди повертає 0, оскільки максимум є виключним.


42

Q

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

Q завжди ініціалізує насіння випадкових чисел з однаковим значенням.


8
так що в основному це зовсім не випадково
Сем Кремер

3
@SamCreamer Мета питання полягає в тому, щоб зробити висновок не випадковим. Але це виглядає випадковим чином, тому він точно підходить до законопроекту
Cruncher

4
Вибачте, я мав на увазі випадкові числа Q не такі випадкові, це питання, безумовно, відповідає критеріям. Не означав натрапити на такий спосіб!
Сем Кремер

Так, значить, ви повинні знайти власний спосіб генерувати випадкове насіння кожного разу, коли ви хочете використовувати rand? Звучить ... корисно.
DLeh

1
Можна встановити випадкове насіння вручну дуже легко ... запустіть перекладача з -S 1234опції або зробіть \S 1234з перекладача
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";

Друкує: Person X is buying: Jeff(де X від 0-4)

Трохи зловживаючи скалярним контекстом. @index = int(rand() * 5)розміщує випадкове ціле число від 0 - 4 до 0-ї позиції @indexсписку. Друкуючи масив, він належним чином друкує випадкове ціле число в @index, але при використанні в якості індексу масиву в $people[@index]@index використовує скалярний контекст, надаючи йому значення розміру списку, тобто 1.

Цікаво, що @people[@index]він індексує належним чином.

Цікаво, @people[@index]що хеш-фрагмент у Perl @indexє таким, що його оцінюють у контексті списку; у цьому випадку це єдиний список записів, і тому він працює правильно


Тож у C (++) термінах відбувається неявне перетворення зі списку в скалярне, тому що при індексації очікується скаляр?
iFreilicht

@iFreilicht Правильно. У Perl вирази можна оцінювати як список або як скаляр, залежно від місця їх появи. В результаті один і той же вираз може означати різні речі, залежно від контексту. Змінна списку (тобто змінна з @префіксом) у "контексті списку" інтерпретується як усі її елементи, але у "скалярному контексті" - скаляр, рівний загальній кількості елементів у списку. Отже, всередині рядка змінна списку має контекст списку і стає інтерпольованою, і ми отримуємо Person X is buying. Але як індекс масиву він набуває скалярний контекст, і його інтерпретують як 1.
Аллен Г

3
Проблема в тому, що коли бачить програміст Perl my @index = ..., він одразу дивується "WTF ?!".
дероберт

@derobert, Чому б ти дивувався? Ви бачите подібний код досить часто ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;і т. Д.
Маттіас,

@Matthias тому, що рядок полягає у виборі та зберіганні єдиного значення, а замість скалярного він зберігається в масиві.
дероберт

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

Це завжди бере Джулі.

Він має дужки всередині квадратних дужок, і оператор комами повертає значення свого правого операнда.
Це також дуже легко пропустити. Я раніше її пропускав у реальному коді.


Це приємно. Нарешті, використання цього жахливого, жахливого оператора.
Кін

5
Кома в цьому контексті технічно є оператором, а не роздільником. ecma-international.org/ecma-262/5.1/#sec-11.14 І це жахливо. Якщо ви не хочете, щоб ваш код був важким для читання. Як ви робите тут. Отже, кудо.
Кін

2
@Cory Так, я погоджуюся - хоча я весь час використовую його для Code Golf із виразами функцій (наприклад (a,b)=>(a=b[0],b)). Я уточнив свою відповідь.
Зубна щітка

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

Хитрість полягає в тому, що метод new Random().NextDouble()повертає вдвічі між 0 і 1. Застосовуючи Math.Floor()це значення, воно завжди буде 0.


24
Це не витримало мого швидкого погляду. ;)
Мартін Ендер

1
@TimS. так як це? : P
Кнерд

2
+1, набагато краще - я знаю, що ти насправді робиш, але це може обдурити когось, не надто знайомого з API.
Тім С.

1
Я не знаю про це. Якщо ви збираєтеся вказати насіння, чому б просто не використати правильний спосіб отримання "випадкового" int:var random = new Random(5); var id = random.NextInt(5);
clcto

2
@clcto На мою думку, включити це вдвічі більше шансів змусити когось подвоїтись, запитати, чому, і побачити проблему. Якщо включити його один раз, а потім включити непотрібний код, це дає трохи перенаправлення / непомірності. Бонус: якщо хтось виправить одну з помилок, існує інша.
Тім С.

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

Підказка:

Зробіть насіння з GUID. У путівників можливе зіткнення 4 × 10-10. Супер випадковий.

Відповідь:

Принаймні, коли ви використовуєте Guid.NewGuid(), ого! (Підлий спосіб зробити насіння завжди 0). Також безглуздо (int) для неправильного спрямування.


Інший спосіб , яким я міг би це зробити, щоб отримати AddRangeзаплуталися з Concatпри додаванні імен до List<string>. Мені прийшло в голову мати хешсет із підлий IEqualityComparer, але це було б занадто незвично. На мій кредит, було не так багато (якщо вони є) насіннєвих відповідей, коли я публікував це.
Натан Купер

Я здогадуюсь, ви мали таку саму ідею, як і я, але ви були трохи швидші і зробили це трохи важче. +1!
tsavinho

7
Посів генератора випадкових чисел - очевидний трюк, але ви його тут блискуче приховали. Прекрасна робота.
TRiG

18

bash / coreutils

Це взято майже дослівно зі сценарію, який я написав для подібної мети.

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

Навіть забути використовувати верхній регістр R - це помилка, яку я періодично робив у сценаріях реального життя.


3
ви могли б дати краще пояснення? Ваш поточний дійсно короткий і не корисний тому, хто насправді не знайомий з башем.
iFreilicht

6
-rвизначає зворотний (лексикографічний) сорт, тому Стів завжди буде обраний. Це можна було б сприймати як невинну друкарню -Rвипадкових сортів
Макс

3
Це гарне нагадування не довіряти коментарям, а уважно читати код!
TecBrat

16

Рубін

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

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

З цим було б правильно працювати sort_by, але sortочікується, що функція порівняння працює так <=>. Результат rand () завжди буде позитивним, тому він завжди буде отримувати рівноцінні результати за умови sortдетермінації алгоритму вашої реалізації Ruby . Мій Ruby 1.9.3 завжди видає Джулі.


12

Рубін

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

puts names[rand() % 5]

rand() без аргументів створюється випадковий проміжок між 0 і 1. Отже, модуль 5 нічого не робить, а при нарізанні масиву з аргументом float Ruby просто округляє його вниз, тому це завжди повертає Джона.


11

Perl

три srands зроблять це втричі більш випадковим!

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

пояснення

у perl немає $ RANDOM, це невизначена змінна. код завжди поверне перший елемент зі списку - напої на Джон :)

редагувати:

переглянувши код, один із п’яти хлопців вирішив виправити очевидну помилку, створивши наступну програму:

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

ви можете сказати, хто це зробив, просто подивившись на код?

пояснення:

у Perl $#arrayповертає індекс останнього елемента; так як масиви нуля, дали посилання на масив з п'ятьма елементами, $#$aref_peopleбуде 4.
randповертає випадкове число більше або рівне нулю і менше його параметра, тому воно ніколи не повернеться 4, що фактично означає, що Джулі ніколи не купуватиме напої :)


1
$RANDOM- реальна особливість у bash, ksh та zsh (але не в perl).
kernigh

10

Пітон

Всім відомо, що ви не можете довіряти випадковості в такому невеликому зразковому просторі; щоб зробити це по-справжньому випадковим, я відмовився від застарілого методу вибору імені зі списку, і замість цього моя програма викладе зовсім випадкове ім’я. Оскільки в більшості імен в офісі було 4 літери, ми вирішимо це.

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)

Природно, я зробив деякі підготовчі роботи, щоб переконатися, що я підбираю потрібне насіння.


15
Насіннєве генерування випадкових чисел із константою є занадто очевидним ..
Брендан Довгий

@BrendanLong Це б точно підняло брови. Люди хотіли б перевірити його, щоб переконатися в його випадковості. А коли ні, здогадайтесь, хто купує напої.
JFA

10

С

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

Вибач, Джеффе!

Після декількох ітерацій r == 1 мод 5 через математику. Мораль: не пишіть власний PRNG, якщо ви погано займаєтесь математикою. :)


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

Розмір вектора фактично дорівнює 1 завдяки дужкам, які використовуються у списку ініціалізатора. Оператор Comma відкине всі імена та поверне останнє, отже, покупець завжди Рой.


10

Скала

Я знаю, що мої користувачі будуть скептично налаштовані, тому я включив доказ того, що моя випадковість справді справедлива!

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
  }

}

Один приклад запуску:

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

Якщо комусь не пощастить, Джон завжди купуватиме напої.

"Доказ" випадковості покладається на той факт, що rand(1, 4) * rand(1, 4) % 5все ще рівномірно розподілений між 1 і 4 включно. Але rand(1, 5) * rand(1, 5) % 6є виродженим. Існує можливість отримати 0, який потім зробить кінцевий результат 0 незалежно від решти "випадковості".


10

Javascript (з Underscore.js )

Оскільки у JavaScript немає вбудованої перетасовки, ми будемо використовувати Underscore.js

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

_.shuffle повертає перетасований масив, він не змінюється на місці, як Array.prototype.sort () , вибачте Джон


9

JavaScript

Друга спроба, ця трохи складніше:

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

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

argumentsЗмінна локально доступні для функцій і являє собою масив з усіх аргументів , переданих у функцію. Використовуючи просте іменування та передаючи масив до самої функції, ви можете підробити те, що ми приймаємо не довжину масиву, а насправді довжину списку аргументів (що становить 1). Це можна ще краще виконати за допомогою спеціальних символів або типу шрифту.


Це було не найскладніше. Кожен, хто сконструював довільну Nфункцію в JavaScript, знає про цю argumentsзмінну.
Conor O'Brien

8

C ++

Для справедливості нам слід проводити багато, багато випробувань і обирати того, кого обирають найчастіше.

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

У чому цінність 1<<31? Вибач, Джон.


Відповідь на ваше спойлерне питання - UB. Я не визначився, якщо це робить краще чи гірше.
nwp

@nwp Ну, звичайно, але десь існує, що int є 32-розрядним доповненням 2, що, здається, має місце навіть у 64-розрядному (з gcc). Я ще не тестував на Кланг.
пухнастий

Ні, він не тримається ніде, де інта є 32-но доповненням 2. Значення 1 << 31 не визначено. Вам пощастило, якщо невизначена поведінка змушує компілятор вибрати все, що йому здається, і оскільки він зроблений для швидкості, він просто вирішить нічого не робити, що станеться тим, що ви хочете.
nwp

@nwp незважаючи 1<<31 == 0x80000000ні на що, за самим визначенням <<, і на 32-розрядному додатку 2, це INT_MIN. Ви, можливо, замислюєтесь над тим, 1<<32що може чи ні == 0? (Тому що на x86 1<<32зазвичай оцінюється до 1 ...)
пухнастий

@nwp Це фактично визначено реалізацією. Тепер, якщо ми говорили про C, то це було б не визначено.
Стюарт Олсен

7

T-SQL (2008+)

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

Пояснення:

У MS SQL Server RAND()оцінюється лише один раз за виконання. Кожному імені завжди присвоюється однаковий номер, залишаючи початкове замовлення. Іван перший. Відстій для Джона.

Пропоноване вдосконалення:

T-SQL може створювати пристойну якість, за рядком випадкових чисел за допомогою RAND(CHECKSUM(NEWID())).


Я думаю, що ЗАМОВЛЕННЯ NEWID () буде достатньо (не потрібно перевіряти)
Jacob

7

Луа

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()Для цілей часу, os.time()це те, що слід використовувати math.randomseedдля гарної RNG. На жаль, Джулі завжди купує (принаймні, на моєму комп’ютері).


math.random()без аргументів також повертає число в діапазоні [0,1). -1 за те, що не ловити це.
mniip

@mniip: Воістину теж заслужив! Я зараз це виправив.
Кайл Канос

6

Ідіоматичний C ++ 11

Коли входять напої, особливо важливо бути в курсі останніх стандартів та стилів кодування; це чудовий приклад високоефективного та відповідного до ідіоми вибору імен C ++ 11.

Він виводиться з системного годинника і кожного разу виводить насіння разом з ім'ям для перевірки.

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

Спробуйте це в прямому ефірі: http://ideone.com/KOet5H

Гаразд, це насправді дуже хороший код; Є багато червоних оселедців, щоб змусити вас занадто уважно придивитися до коду, щоб помітити очевидне - що RNG ніколи насправді не висівається :) У цьому випадку seedце лише ціле число, і, хоча це виглядає engine, передається як параметр a функцію висіву, вона насправді просто ігнорується. Насінна змінна дійсно встановлюється з годинника, тому її можна виводити в кінці разом з назвою, щоб нанести шкоду травмі, але все одно завжди буде Стів, який купує напої.


1
Мене вбиває те, що він не використовує список ініціалізаторів для імен. По крайней мере, ви , безумовно , вдалося забезпечити код , який просто відчуває себе над- сконструйовану. Я не можу сказати, чи це через "відповідність" чи всі шумові коментарі: P
vmrob

6

JavaScript

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

Ну, вибачте, Math.randomне приймає параметр і завжди повертає число з [0, 1). І все-таки це щаслива варіативна функція і не скаржиться на аргументи!


5

Пітон

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 (випадковий) дає постійний рядок; не випадкове значення


6
Дещо нерелевантна примітка: якщо ви використовуєте Python 3.2 або пізнішої версії, другим аргументом random.seed()повинен бути 2(за замовчуванням). Якщо ви перейдете version=1, hash()рядок буде використано як насіння замість цілого рядка, і оскільки Python випадковим чином насіннєвих хеш-значень рядків починається з 3.2, ви отримаєте фактично випадкове ім’я.
Blacklight Shining

5

Perl

Еммі краще не забути гаманець! Працює під strictі під 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.

Пояснення тут .


Perl 5.18 трохи змінив це, ввівши рандомізацію хеш-ключів (щоб уникнути атак складності хеш-зіткнення).
Конрад Боровський

4

JavaScript

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

В |0результати в 0 весь час , але схоже , що це роблять деякі інші округлення.


Мені це подобається. Хоча я б зробив parseInt(Math.random(0, 4))і, можливо, додав коментарі на кшталт - Math.randomповертає дубль, тому конвертуй його в перше число
Клавдіу

5
Підступність насправді полягає в тому, що Math.randomнічого не цікавить наші мізерні параметри. Він вибирає числа по-своєму. |0правильно округляти несподіваний результат, і тому не є джерелом якого - або обману.
Кін

|0Для когось це дуже очевидно (для всіх нас, швидше за все), але я б сподівався, що є багато тих, хто не має уявлення, що це робить. Це група, на яку я покладався на хитрість.
Метт

3
Я маю в виду @ Matt , що |0, якщо ви знаєте , що він робить, схоже , що це округлення вниз, і це буде округлення вниз, так що це не обман. (І якщо хтось не має уявлення, що |0робить, тоді не потрібно використовувати оманливий код; ви можете просто сказати їм все, що ви хочете, щоб вони повірили.) Натомість несподівана поведінка у вашій відповіді заснована на тому, що Math.random(0,4)функціонально ідентичний Math.random(), оскільки Math.randomне використовує параметрів.
Кін

4

J

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

Бідна Джулі ... Дрібниці: це, можливо, було найчистішим J, що я коли-небудь писав ...

Цей код насправді правильний, за винятком однієї речі. ?.- це рівномірний rng: ?.5завжди повертається 4. ?5було б правильно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.