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


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.