Случайный сценарий, который на самом деле не случайный

106

В качестве маленькой шутки в офисе кто-то захотел сценарий, который случайным образом выбирает имя, и сказал, что человек сделает несколько напитков.

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

Я подумал, что было бы забавно создать сценарий, который на первый взгляд кажется случайным, но на самом деле всегда дает одного и того же человека в качестве выходных данных (до вас, кого вы выберете).

Ответ с наибольшим количеством голосов побеждает через неделю

И победитель....

Пол Р. с (в настоящее время) 158 голосами.

Ответы здесь замечательные, и если у кого-то еще есть какие-либо идеи, которые еще не были опубликованы, пожалуйста, добавьте их, я люблю читать их.

TMH
источник
44
xkcd.com/221
AstroCB
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;каждом операторе switch был символ после каждого. Как бы то ни было, каждый случай «проваливается» на следующий, поэтому бедная Джули всегда заканчивает тем, что покупает напитки.

Пол Р
источник
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.

MonoCell
источник
25
Вы должны любить PHP - и даже лучше, он будет редко выбирать кого-то другого. Так что если вам повезет, на первый взгляд это будет немного предвзято
Falco
142
+1000 за «... оповещение программиста о потенциальной ошибке считается смертельным грехом в PHP».
Jsedano
85

Haskell

Он слишком прозрачен, если всегда возвращает одно и то же имя, поэтому попробуйте следующее

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поток никогда не запустится

MonoCell
источник
24
Это дьявольское!
Daenyth
8
Похоже на фотографирование кости, которая еще не остановилась.
Ви.
1
@Vi. Это хорошая аналогия. К счастью, использование MVars гарантирует, что изображение не будет размытым. :)
одноячейка
@monocell Технически, даже фотография движущегося объекта может быть четкой.
ghosts_in_the_code
75

Баш - максимальная простота

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

#!/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 /
йети
Что произойдет, если вы 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]);
        }
    }
}

Это может не обмануть людей, знакомых с .Net API, но люди, которые не знают его, могут поверить, что 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, так как максимум является исключительным.

Rynant
источник
42

Q

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

Q всегда инициализирует начальное число случайных чисел одним и тем же значением.

skeevey
источник
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
@ Кори Да, я согласен - хотя я все время использую его для 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.

Knerd
источник
24
Это не выдержало моего быстрого взгляда. ;)
Мартин Эндер
1
@TimS. как это? : P
Knerd
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>. Мне приходило в голову иметь Hashset с хитрым IEqualityComparer, но это было бы слишком необычно. На мой счет не было много (если таковые имеются) основанные на семени ответы, когда я отправил это.
Натан Купер
Я предполагаю, что у вас была та же идея, что и у меня, но вы были немного быстрее и сделали ее немного труднее увидеть. +1!
цавиньо
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, я ошибаюсь в реальных сценариях.

kasperd
источник
3
не могли бы вы дать лучшее объяснение? Ваш текущий очень короткий и не полезен для тех, кто не очень знаком с bash.
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 всегда выводит Джули.

histocrat
источник
12

Рубин

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

puts names[rand() % 5]

rand() без аргументов выдает случайное число с плавающей точкой от 0 до 1. Таким образом, по модулю 5 ничего не происходит, а при нарезке на массив с аргументом с плавающей запятой Ruby просто округляет его, так что это всегда возвращает Джона.

histocrat
источник
11

Perl

три srandс сделает это в три раза больше случайным!

#!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, что фактически означает, что Джули никогда не будет покупать напитки :)

китайский Perl гот
источник
1
$RANDOMэто реальная особенность в bash, ksh и zsh (но не в perl).
Керни
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)

Естественно, я сделал некоторые подготовительные работы, чтобы убедиться, что я выбрал правильное семя.

Tal
источник
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 mod 5 из-за математики. Мораль: не пишите свой собственный PRNG, если вы плохо разбираетесь в математике. :)

CPRI
источник
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 из-за круглых скобок, используемых в списке инициализатора. Оператор запятой отбрасывает все имена и возвращает последнее, поэтому покупателем всегда является Рой.

Tomasz
источник
10

Scala

Я знаю, что мои пользователи будут настроены скептически, поэтому я включил доказательство того, что моя случайность действительно справедлива!

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 не имеет встроенного shuffle, мы будем использовать 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). Это может быть даже лучше выполнено, используя специальные символы или тип шрифта.

thomaux
источник
Это было не самым трудным для обнаружения. Любой, кто создал произвольную N-арную функцию в JavaScript, знает о argumentsпеременной.
Конор О'Брайен,
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). Я не проверял на Clang, хотя.
пушистый
Нет, это не имеет места где int это 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())).

comfortablydrei
источник
Я думаю, что ORDER BY NEWID () будет достаточно (нет необходимости в CHECKSUM)
Джейкоб
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()это для временных целей, os.time()это то , что должно быть использовано math.randomseedдля хорошего RNG. К сожалению, Джули всегда покупает (по крайней мере, на моем компьютере).

Кайл Канос
источник
math.random()без аргументов также возвращает число в диапазоне [0,1). -1 за то что не уловил.
Мниип
@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

Итак, это на самом деле довольно хороший код в целом; Есть много красных сельдей, которые заставляют вас слишком внимательно присмотреться к коду, чтобы заметить очевидное - что ГСЧ на самом деле никогда не засеивается :) В этом случае seedэто просто целое число, и, хотя оно выглядит так, engineоно передается в качестве параметра функция посева, это на самом деле просто игнорируется. Переменная seed на самом деле устанавливается с часов, поэтому в конце она может быть выведена вместе с именем, чтобы добавить оскорбление ране, но все равно всегда будет Стив, который покупает напитки.

буйство
источник
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 (random) дает постоянную строку; не случайное значение

QuadrExAtt
источник
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 все время , но похоже , что это делают некоторые другие округление.

Matt
источник
Мне это нравится. Хотя я хотел бы сделать parseInt(Math.random(0, 4))и, возможно, добавить комментарии типа - Math.randomвозвращает двойное число, поэтому сначала преобразуйте его в целое число
Claudiu
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было бы правильно.

ɐɔıʇǝɥʇuʎs
источник