Script aleatório que não é realmente aleatório

106

Como uma pequena piada no escritório, alguém queria um roteiro que escolhesse um nome aleatoriamente, e essa pessoa fará uma rodada de bebidas.

Vamos chamar as pessoas de John, Jeff, Emma, ​​Steve e Julie.

Eu pensei que seria engraçado fazer um script que parecesse aleatório rapidamente, mas na verdade sempre dá a mesma pessoa que a saída (depende de você escolher).

A resposta mais votada vence depois de uma semana

E o vencedor é....

Paul R com (atualmente) 158 votos.

As respostas aqui são ótimas e, se alguém tiver outras idéias que ainda não foram publicadas, adicione-as, adoro ler.

TMH
fonte
44
xkcd.com/221
AstroCB 16/06
6
@AstroCB um dos meus favoritos. Logo atrás de mesas de bobby.
Cruncher
50
Parece que seria mais furtivo se fosse aleatório, exceto por nunca escolher uma pessoa.
Brendan Longo
6
@AstroCB este também é fantástico: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb
3
Passei pela primeira página: a maioria das respostas sempre escolhe John, a segunda mais alta é Julie, Jeff é escolhido raramente e Steve por 1. Até Ray foi escolhido por um, mas ninguém escolheu Emma. Moral da história: quando estiver em uma fila para decidir aleatoriamente quem comprará as bebidas, nomeie-se Emma.
Variável miserável

Respostas:

171

C

É importante decidir quem está comprando o mais rápido possível, para não perder um tempo precioso de bebida - portanto, C é a escolha óbvia para obter o máximo desempenho:

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

Explicação:

Isso funcionaria muito bem se houvesse um break;após cada caso na instrução switch. No entanto, como cada caso "passa" para o próximo, a pobre Julie sempre acaba comprando as bebidas.

Paul R
fonte
17
+1 por desempenho - muito mais rápido do que rolar um dado físico! ;)
Jwosty
16
Estou pensando em otimizá-lo ainda mais, talvez com SIMD ou GPGPU, apenas para obter um pouco mais de desempenho. ;-)
Paul R
7
Absolutamente real ao vivo aplicável. Ninguém jamais questionaria que foi um acidente nem um pouco.
IFreilicht
5
Sou só eu ou é óbvio demais para perceber?
Alvin Wong
3
@AlvinWong Eu não percebi imediatamente. Então, novamente, eu não uso C regularmente, ou qualquer outro idioma que descende do BCPL.
Rhymoid
164

PHP

Não foi possível deixar isso para trás, então aqui está outro:

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

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

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

Na verdade, não é garantido que ele produza john, mas as chances são muito boas. Felizmente, o PHP aceita o que o / dev / random tem a oferecer, visto que (provavelmente) não pode analisá-lo e criar o número 0 bastante razoável. Afinal, alertar o programador sobre um erro em potencial é considerado um pecado mortal no PHP.

monocelular
fonte
25
Você adora PHP - e, melhor ainda, às vezes raramente escolhe outra pessoa. Então, se você tiver sorte ela só vai parecer um pouco tendenciosa em primeiro lugar
Falco
142
+1000 para "... alertar o programador sobre um erro em potencial é considerado um pecado mortal no PHP."
jsedano
85

Haskell

É muito transparente se sempre retornar o mesmo nome, então tente o seguinte

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

Sempre que você quiser que seja aleatório:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

E para o seu infeliz alvo:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

O Hugs implementa apenas multitarefa cooperativa, portanto o rotatethread nunca será executado

monocelular
fonte
24
Isso é diabólico!
Daenyth
8
É como fotografar um dado que ainda não parou de se mover.
Vi.
1
@Vi. Essa é uma boa analogia. Felizmente, o uso do MVars garante que a imagem não fique embaçada. :)
monocell
@monocell Bem, tecnicamente, mesmo uma foto de um objeto em movimento pode ser clara.
ghosts_in_the_code
75

Bash - simplicidade máxima

Um exemplo muito simples - vamos evitar problemas ao fazer o livro. Não se esqueça de semear o gerador do relógio do sistema para obter um bom resultado!

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

Isso depende do usuário não saber o que o $SECONDSconstruído realmente faz; retorna o número de segundos desde o início do shell atual. Como está em um script, o shell sempre começou zero segundos atrás, então o gerador é sempre semeado 0e Julie sempre compra a cerveja.

Bônus:

Este resiste muito bem ao escrutínio; Se você digitar o mesmo código na linha de comando em vez de em um script, ele fornecerá resultados aleatórios, porque $SECONDSretornará o período de tempo em que o shell interativo do usuário esteve em execução.

Tumulto
fonte
9
\ o / Média !!! Realmente significa !!! $SECONDSftw! \ o /
yeti
O que acontece se você fizer sourceisso, em vez de apenas executá-lo? O shebang ainda acionará uma nova concha ou algo assim?
jpmc26
1
@ jpmc26: se você executá- sourcelo, é exatamente o mesmo que se você tivesse digitado os comandos na linha de comando; #! / bin / bash é um comentário, por isso é ignorado. Isso vale para qualquer script.
Motim
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]);
        }
    }
}

Isso pode não enganar as pessoas que estão familiarizadas com a API .Net, mas as pessoas que não a conhecem podem acreditar que OrderBymodifica o objeto que você chama, e é um erro plausível para um novato na API.

Peter Taylor
fonte
1
Mesmo que o OrderBy hipoteticamente modificasse o objeto, essa chamada realmente classificaria a lista aleatoriamente? Como alguém não familiarizado com o .NET, meu primeiro palpite foi que, como rng.Next()é chamado apenas uma vez, a matriz seria classificada por uma constante, resultando em nenhuma alteração (ou uma alteração que depende apenas do algoritmo de classificação).
Brilliand
1
@Brilliand O argumento passado para OrderBy não é um valor estático, é executado toda vez que um elemento é classificado e, nesse caso, retorna valores aleatórios sem comparar nenhum valor. Na verdade, funcionaria corretamente se a linha fosse #names = names.OrderBy(name => rng.Next());
user3188175:
1
A =>indica que esta é uma expressão lambda C # (encerramento).
Snowbody
44

PowerShell

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

Isso sempre será exibido John.

$namesé um System.Collections.Hashtableque não possui uma Lengthpropriedade. A partir do PowerShell v3, Length(e também Count) pode ser usado como uma propriedade em qualquer objeto. Se um objeto não tiver a propriedade, ele retornará 1quando o objeto não for nulo; caso contrário, ele retornará 0. Então, na minha resposta, $names.Lengthavalia como 1 e random -maximum 1sempre retorna 0, pois o máximo é exclusivo.

Rynant
fonte
42

Q

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

Q sempre inicializa sua semente de número aleatório com o mesmo valor.

skeevey
fonte
8
Então, basicamente, não é aleatório em tudo
Sam Creamer
3
@SamCreamer O objetivo da pergunta é muito para tornar a saída não aleatória. Mas isso faz parecer aleatório por isso definitivamente se encaixa no projeto
Cruncher
4
Desculpe, eu quis dizer que os números aleatórios de Q não são tão aleatórios, essa pergunta certamente atende aos critérios. Não quis me deparar com esse caminho!
Sam Creamer
Sim, então você precisa encontrar seu próprio caminho para gerar uma semente aleatória toda vez que quiser usar o rand? Parece ... útil.
DLeh
1
Pode definir a semente aleatória manualmente com muita facilidade ... iniciar o interpretador com a -S 1234opção ou fazer \S 1234a partir do intérprete
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";

Impressões: Person X is buying: Jeff(onde X é de 0 a 4)

Abusar um pouco o contexto escalar. @index = int(rand() * 5)coloca um número inteiro aleatório de 0 a 4 na posição 0 da @indexlista. Ao imprimir a matriz, imprime corretamente o número inteiro aleatório em @index, mas ao usar como um índice de matriz em $people[@index]@index usa o contexto escalar, fornecendo o valor do tamanho da lista, ou seja 1.

Curiosamente, @people[@index]torna o índice corretamente.

Curiosamente, @people[@index]existe uma fatia de hash no Perl, e @indexé avaliada no contexto da lista; nesse caso, é uma lista de entradas únicas e é por isso que funciona corretamente

Allen G
fonte
Então, em termos de C (++), há uma conversão implícita da lista em escalar, porque, durante a indexação, é esperado um escalar?
IFreilicht
@iFreilicht Correct. No Perl, as expressões podem ser avaliadas como uma lista ou como escalar, dependendo de onde elas aparecem. Como resultado, a mesma expressão pode significar coisas diferentes, dependendo do contexto. Uma variável de lista (ou seja, uma variável com o @prefixo), no "contexto da lista", é interpretada como todos os seus elementos, mas no "contexto escalar", é um escalar igual ao número total de elementos na lista. Portanto, dentro da string, a variável list tem contexto de lista e é interpolada, e nós obtemos Person X is buying. Mas, como um índice da matriz, fica contexto escalar, e é interpretado como 1.
Allen G
3
O problema é que, quando um programador Perl vê my @index = ..., ele imediatamente se pergunta "WTF ?!".
21814 derobert
@derobert, por que você se pergunta? Você vê um código como que, muitas vezes ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;etc
Matthias
@ Matthias porque a linha é escolher e armazenar um único valor e, em vez de um escalar, ele está sendo armazenado em uma matriz.
26414 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]);

Ele sempre pega Julie.

Possui colchetes dentro dos colchetes, e o operador de vírgula retorna o valor do seu operando direito.
Também é muito fácil de perder. Eu já perdi isso antes em código real .

Escova de dente
fonte
Isso é delicioso. Finalmente, um uso para aquele operador terrível e terrível.
Keen
5
A vírgula nesse contexto é tecnicamente um operador, e não um separador. ecma-international.org/ecma-262/5.1/#sec-11.14 E é terrível. A menos que você queira que seu código seja difícil de ler. Como você faz aqui. Então, parabéns.
Keen
2
@ Cory Sim, eu concordo - embora eu o use o tempo todo para o Code Golf com expressões de função (por exemplo (a,b)=>(a=b[0],b)). Eu esclareci minha resposta.
Escova de dentes
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]);
        }
    }
}

O truque é que o método new Random().NextDouble()retorna um duplo entre 0 e 1. Ao aplicar Math.Floor()esse valor, ele sempre será 0.

Knerd
fonte
24
Não resistiu ao meu olhar rápido. ;)
Martin Ender
1
@TimS. Curtiu isso? : P
Knerd 16/06
2
+1, muito melhor - eu sei o que você realmente está fazendo, mas isso pode enganar alguém que não conhece muito a API.
Tim S.Jul
1
Eu não sei sobre isso. Se você estiver indo para especificar uma semente, por que não usar a maneira correta de conseguir um int "aleatório":var random = new Random(5); var id = random.NextInt(5);
clcto
2
@clcto Na minha opinião, incluí-lo duas vezes é mais provável que alguém dê uma olhada dupla, pergunte o porquê e veja o problema. Incluir uma vez e depois incluir código desnecessário posteriormente fornece um pouco de redirecionamento / clandestinidade. Bônus: se alguém corrige um dos erros, existe outro.
Tim S.
18

C #

var names = new string[] {"John", "Jeff", "Emma", "Steve", "Julie"};
var guidBasedSeed = BitConverter.ToInt32(new Guid().ToByteArray(), 0);
var prng = new Random(guidBasedSeed);
var rn = (int)prng.Next(0, names.Length);
Console.WriteLine(names[rn]);

Dica:

Gere semente a partir do GUID. Guias têm 4 × 10-10 de chance de colisão. Super aleatório.

Responda:

Pelo menos quando você usa Guid.NewGuid(), gritos! (Maneira sorrateira de fazer sementes sempre 0). Também inútil (int) para direcionamento incorreto.

Nathan Cooper
fonte
A outra maneira de fazer isso é ficar AddRangeconfuso Concatao adicionar nomes a um List<string>. Ocorreu-me ter um Hashset com um IEqualityComparer sorrateiro, mas seria muito incomum. No meu crédito, não havia muitas (se houver) respostas baseadas em sementes quando eu postei isso.
Nathan Cooper
Acho que você teve a mesma ideia que eu, mas você foi um pouco mais rápido e dificultou a visão. +1!
tsavinho 16/06
7
Semear o gerador de números aleatórios é um truque óbvio, mas você o escondeu de maneira brilhante aqui. Belo trabalho.
TRiG
18

bash / coreutils

Isso é tirado quase literalmente de um script que escrevi para uma finalidade semelhante.

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

Mesmo esquecer de usar um R maiúsculo é um erro que cometi ocasionalmente em scripts da vida real.

Kasperd
fonte
3
você poderia dar uma explicação melhor? O atual é muito curto e não é útil para alguém que não está realmente familiarizado com o bash.
IFreilicht
6
-respecifica a classificação reversa (lexicográfica), para que Steve sempre seja escolhido. Pode ser visto como um erro de digitação inocente -Rde tipo aleatório
Max
3
Esse é um bom lembrete para não confiar nos comentários, mas ler atentamente o código!
TecBrat
16

Rubi

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

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

Isso funcionaria corretamente sort_by, mas sortespera uma função de comparação que funcione como <=>. O resultado de rand () sempre será positivo, portanto sempre produzirá resultados equivalentes, desde que o sortalgoritmo da sua implementação Ruby seja determinístico. Meu Ruby 1.9.3 sempre gera Julie.

histocrata
fonte
12

Rubi

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

puts names[rand() % 5]

rand() sem argumentos produz um float aleatório entre 0 e 1. Portanto, o módulo 5 não faz nada e, ao cortar em uma matriz com um argumento float, Ruby apenas o arredonda para baixo, então isso sempre retorna John.

histocrata
fonte
11

Perl

três srands o tornarão três vezes mais aleatório!

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

explicação

não há $ RANDOM em perl, é uma variável indefinida. o código sempre retornará o primeiro elemento da lista - drinks em John :)

editar:

depois de passar pelo código, um dos cinco caras decidiu corrigir o erro óbvio, produzindo o seguinte programa:

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

você pode dizer quem fez isso apenas olhando o código?

explicação:

em Perl, $#arrayretorna o índice do último elemento; como matrizes são baseadas em zero, dada uma referência a uma matriz com cinco elementos, $#$aref_peopleserá 4.
randretorna um número aleatório maior ou igual a zero e menor que seu parâmetro, portanto nunca retornará 4, o que significa efetivamente que Julie nunca comprará bebidas :)

gótico chinês do perl
fonte
1
$RANDOMé um recurso real no bash, ksh e zsh (mas não no perl).
kernigh
10

Pitão

Todo mundo sabe que você não pode confiar na aleatoriedade em um espaço de amostra tão pequeno; para torná-lo verdadeiramente aleatório, abandonei o método desatualizado de escolher um nome em uma lista e, em vez disso, meu programa soletrará um nome completamente aleatório. Como a maioria dos nomes no escritório tinha quatro letras, nós aceitaremos isso.

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)

Naturalmente, fiz alguns trabalhos de preparação para garantir a colheita da semente certa.

Tal
fonte
15
Semeando o número aleatório gerar com uma constante é muito óbvio ..
Brendan Longo
@BrendanLong Definitivamente, levantaria as sobrancelhas. As pessoas querem testá-lo para garantir que seja aleatório. E quando não estiver, adivinhe quem está comprando bebidas.
JFA 25/06
10

C

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
char *name[]={"John", "Jeff", "Emma", "Steeve", "Julie"};

int i;
int n=rand()%10000;
int r=3;

for (i=0; i<10000+n; i++) // random number of iteration
    {
    r=(r*r)%10000; // my own PRNG (square and mod)
    }

printf("%s", name[r%5] );
}

Desculpe Jeff!

Após algumas iterações, r == 1 mod 5, por causa da matemática. Moralidade: não escreva seu próprio PRNG se você é ruim em matemática. :)

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

O tamanho do vetor é realmente 1 devido aos parênteses usados ​​na lista de inicializadores. O operador de vírgula descartará todos os nomes e retornará o último, portanto, o comprador é sempre Roy.

tomasz
fonte
10

Scala

Sei que meus usuários serão céticos, por isso incluí uma prova de que minha aleatoriedade é realmente justa!

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
  }

}

Um exemplo de execução:

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

A menos que alguém tenha muita sorte, John sempre comprará as bebidas.

A "prova" da aleatoriedade baseia-se no fato de que rand(1, 4) * rand(1, 4) % 5ainda é distribuído igualmente entre 1 e 4, inclusive. Mas rand(1, 5) * rand(1, 5) % 6é degenerado. Existe a possibilidade de você obter um 0, que tornaria o resultado final 0, independentemente do resto da "aleatoriedade".

Joe K
fonte
10

Javascript (com Underscore.js )

Como o javascript não possui um shuffle incorporado, usaremos Underscore.js

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

_.shuffle retorna a matriz aleatória , ela não se modifica como Array.prototype.sort () , desculpe John

Kristoffer Sall-Storgaard
fonte
9

Javascript

Segunda tentativa, essa é um pouco mais complicada:

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

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

A argumentsvariável é acessível localmente para funções e é uma matriz de todos os argumentos passados ​​para a função. Usando nomes simples e passando uma matriz para a própria função, você pode falsificar que não estamos comprando o comprimento da matriz, mas na verdade o comprimento da lista de argumentos (que é 1). Isso pode ser ainda melhor executado usando caracteres especiais ou um tipo de fonte.

thomaux
fonte
Não foi o mais difícil de detectar. Qualquer pessoa que tenha construído uma Nfunção arbitrária -ary em JavaScript conhece a argumentsvariável.
Conor O'Brien
8

C ++

Para ser justo, devemos executar muitas, muitas tentativas e escolher quem é escolhido com mais frequência.

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

Qual é o valor de 1<<31? Desculpe John.

fofo
fonte
A resposta para sua pergunta de spoiler é UB. Estou indeciso se isso faz é melhor ou pior.
nwp 22/06
@nwp Bem, claro, mas ele mantém em qualquer lugar que int seja o complemento de 32 bits 2, o que parece ser o caso mesmo em 64 bits (com o gcc). Eu não testei no Clang, no entanto.
fofo
Não, ele não acontece em nenhum lugar onde um int seja 32, mas o complemento de 2. O valor de 1 << 31 é indefinido. Você tem sorte, porém, um comportamento indefinido faz com que o compilador escolha o que quer que seja e, como é feito para acelerar, ele simplesmente decide não fazer nada, o que é o que você deseja.
nwp 22/06
@nwp 1<<31 == 0x80000000não importa o que, pela própria definição de <<, e no complemento de 32 bits 2, seja isso INT_MIN. Você está pensando sobre o 1<<32que pode ou não == 0? (Porque em x86, 1<<32geralmente avalia a 1 ...)
macios
@nwp Na verdade, é definido pela implementação. Agora, se nós estávamos falando sobre C, em seguida, seria indefinido.
Stuart Olsen
7

T-SQL (2008+)

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

Explicação:

No MS SQL Server, RAND()avalia apenas uma vez por execução. Cada nome sempre recebe o mesmo número, deixando a ordem original. John é o primeiro. Suga para John.

Melhoria sugerida:

O T-SQL pode produzir números aleatórios por linha com qualidade decente RAND(CHECKSUM(NEWID())).

confortavelmente
fonte
Eu acho que ORDER BY NEWID () será suficiente (não há necessidade de checksum)
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()é para fins de tempo, os.time()é o que deve ser usado math.randomseedpara um bom RNG. Infelizmente, Julie sempre compra (pelo menos no meu computador).

Kyle Kanos
fonte
math.random()sem argumentos também retorna um número no intervalo [0,1). -1 por não entender isso.
Mniip
@mniip: Verdadeiramente merecido também! Eu consertei agora.
Kyle Kanos
6

Idiomatic C ++ 11

Quando as bebidas estão envolvidas, é especialmente importante estar atualizado com os mais recentes padrões e estilos de codificação; este é um ótimo exemplo de um seletor de nomes C ++ 11 altamente eficiente e compatível com o idioma.

Ele é propagado a partir do relógio do sistema e gera a semente junto com o nome para verificação a cada vez.

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

Experimente ao vivo: http://ideone.com/KOet5H

Ok, então isso realmente é um bom código geral; existem muitos arenques vermelhos para fazer você olhar muito de perto o código para perceber o óbvio - que o RNG nunca é realmente propagado :) Nesse caso, seedé apenas um número inteiro e, embora pareça, engineé passado como parâmetro para um função de propagação, na verdade é apenas ignorada. A variável seed é realmente definida a partir do relógio, para que possa ser impressa no final juntamente com o nome para adicionar insulto à lesão, mas ainda será sempre Steve quem compra as bebidas.

Tumulto
fonte
1
Me mata que não usa uma lista de inicializadores para os nomes. No mínimo, você definitivamente conseguiu fornecer código que parece superdimensionado. Eu não posso dizer se é por causa da "conformidade" ou todos os comentários de ruído: P
vmrob
6

Javascript

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

Bem, desculpe, Math.randomnão aceita um parâmetro e sempre retornará um número de [0, 1). Ainda assim, é uma função variada feliz e não se queixa de argumentos!

Bergi
fonte
5

Pitão

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 (aleatório) fornece uma string constante; não é um valor aleatório

QuadrExAtt
fonte
6
Uma observação um tanto irrelevante: se você estiver usando o Python 3.2 ou posterior, o segundo argumento random.seed()deve ser 2(o padrão). Se você passar version=1, o hash()da string será usado como uma semente em vez de toda a string, e como o Python aleatoriamente distribui os valores de hash das strings a partir de 3.2, você obterá um nome realmente aleatório.
Blacklight Shining
5

Perl

Emma era melhor não esquecer sua bolsa! Funciona sob stricte 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.

Explicação aqui .

Zaid
fonte
O Perl 5.18 mudou um pouco isso, introduzindo a randomização da chave de hash (para evitar ataques de complexidade de colisão de hash).
precisa saber é o seguinte
4

Javascript

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

O |0resultado é 0 o tempo todo, mas parece que ele está fazendo algum outro arredondamento.

Matt
fonte
Eu gosto disso. Embora eu faria parseInt(Math.random(0, 4))e talvez adicionar comentários como - Math.randomretorna uma dupla, então convertê-lo para um inteiro primeiro
Claudiu
5
O truque é que, na verdade, Math.randomnão se importa com nossos poucos parâmetros. Ele escolhe os números à sua maneira. o |0está arredondando corretamente o resultado inesperado e, portanto, não é fonte de truques.
Keen
|0é muito óbvio para alguns (provavelmente todos nós), mas aposto que há muitos que não têm ideia do que faz. Esse era o grupo em que eu estava confiando.
Matt
3
@ Matt Quero dizer que |0, se você sabe o que faz, parece que está arredondando para baixo, e está arredondando para baixo, então não é um engano. (E se alguém não tem ideia do que |0faz, então não há utilidade para códigos enganosos; você pode apenas dizer a eles o que quiser que eles acreditem.) Em vez disso, o comportamento inesperado na sua resposta é baseado no fato de que Math.random(0,4)é funcionalmente idêntico a Math.random(), porque Math.randomnão usa parâmetros.
Keen
4

J

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

Pobre Julie ... Curiosidades: esse pode ter sido o J mais limpo que eu já escrevi ...

Este código está realmente correto, exceto por uma coisa. ?.é o rng uniforme: ?.5sempre retornará 4. ?5estaria correto.

ɐɔıʇǝɥʇuʎs
fonte