Script aleatorio que en realidad no es aleatorio

106

Como una pequeña broma en la oficina, alguien quería un guión que escogiera un nombre al azar, y dicha persona haría una ronda de bebidas.

Llamemos a las personas John, Jeff, Emma, ​​Steve y Julie.

Pensé que sería divertido hacer un guión que parezca aleatorio a simple vista, pero que en realidad siempre da a la misma persona que la salida (depende de ti quien elijas).

La respuesta más votada gana después de una semana

Y el ganador es....

Paul R con (actualmente) 158 votos.

Las respuestas aquí son geniales, y si alguien más tiene otras ideas que aún no se han publicado, agréguelas, me encanta leerlas.

TMH
fuente
44
xkcd.com/221
AstroCB
66
@AstroCB uno de mis favoritos. Justo detrás de las mesas de madera.
Cruncher
50
Parece que sería más astuto si fuera al azar, excepto por nunca elegir a una persona.
Reinstale a Monica el
66
@AstroCB este también es fantástico: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb
3
Pasé por la primera página: la mayoría de las respuestas siempre eligen a John, la segunda más alta es Julie, Jeff rara vez es elegido y Steve por 1. Incluso Ray fue elegido por uno, pero nadie eligió a Emma. Moraleja de la historia: cuando hagas una fila para decidir al azar quién comprará las bebidas, llámate Emma.
Variable miserable

Respuestas:

171

C

Es importante decidir quién está comprando lo más rápido posible, para no perder el tiempo precioso de beber, por lo tanto, C es la opción obvia para obtener el máximo rendimiento:

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

Explicación:

Esto funcionaría bien si hubiera un break;después de cada caso en la declaración de cambio. Sin embargo, tal como están las cosas, cada caso "cae" al siguiente, por lo que la pobre Julie siempre termina comprando las bebidas.

Paul R
fuente
17
+1 por rendimiento: ¡mucho más rápido que lanzar un dado físico! ;)
Jwosty
16
Estoy pensando en optimizarlo aún más, tal vez con SIMD o GPGPU, solo para obtener un poco más de rendimiento. ;-)
Paul R
77
Absolutamente real en vivo aplicable. Nadie siquiera cuestionaría que fue un accidente en lo más mínimo.
iFreilicht
55
¿Soy solo yo o es demasiado obvio para detectarlo?
Alvin Wong
3
@AlvinWong No lo noté de inmediato. Por otra parte, no uso C regularmente ni ningún otro lenguaje que descienda de BCPL.
Rhymoid
164

PHP

No podía dejarlo pasar, así que aquí hay otro:

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

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

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

En realidad, esto no garantiza que produzca John, pero las posibilidades son muy buenas. PHP felizmente tomará lo que tenga que ofrecer / dev / random para ver que (probablemente) no pueda analizarlo y en su lugar obtendrá el número muy razonable 0. Después de todo, alertar al programador de un posible error se considera un pecado mortal en PHP.

monocelda
fuente
25
Tienes que amar PHP, y aún mejor, a veces rara vez elegirá a alguien más. Entonces, si tienes suerte, parecerá un poco parcial al principio
Falco
142
+1000 por "... alertar al programador de un posible error se considera un pecado mortal en PHP".
jsedano
85

Haskell

Es demasiado transparente si siempre devuelve el mismo nombre, así que intente lo siguiente

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

Siempre que quieras que sea aleatorio:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

Y para tu objetivo desafortunado:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

Los abrazos solo implementan la multitarea cooperativa, por lo que el rotatehilo nunca se ejecutará

monocelda
fuente
24
Eso es diabólico!
Daenyth
8
Tiene ganas de fotografiar un dado que aún no ha dejado de moverse.
Vi.
1
@Vi. Esa es una buena analogía. Afortunadamente, el uso de MVars garantiza que la imagen no se vea borrosa. :)
monocell
@monocell Bueno, técnicamente, incluso una foto de un objeto en movimiento puede ser clara.
ghosts_in_the_code
75

Bash: máxima simplicidad

Un ejemplo muy simple: evitemos cualquier problema haciéndolo en forma de libro de texto. ¡No olvide sembrar el generador del reloj del sistema para obtener un buen 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

Esto depende de que el usuario no sepa lo $SECONDSque hace realmente el incorporado; devuelve el número de segundos desde que se inició el shell actual. Como está en un guión, el caparazón siempre comenzó hace cero segundos, por lo que el generador siempre está sembrado 0y Julie siempre compra la cerveza.

Prima:

Este se enfrenta bastante bien al escrutinio; Si ingresa el mismo código en la línea de comandos en lugar de en un script, dará resultados aleatorios, ya $SECONDSque devolverá el período de tiempo que el shell interactivo del usuario ha estado ejecutándose.

Alboroto
fuente
99
\ o / Mean !!! ¡¡¡Realmente significa!!! $SECONDSftw! \ o /
yeti
¿Qué sucede si haces sourceesto, en lugar de solo ejecutarlo? ¿El shebang todavía desencadenará un nuevo caparazón o algo así?
jpmc26
1
@ jpmc26: si lo ejecuta con source, es exactamente lo mismo que si hubiera escrito los comandos en la línea de comandos usted mismo; #! / bin / bash es un comentario, por lo que se ignora. Esto es cierto para cualquier script.
Riot
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]);
        }
    }
}

Es posible que esto no engañe a las personas que están familiarizadas con la API .Net, pero las personas que no lo saben pueden creer que OrderBymodifica el objeto al que lo llama, y ​​es un error plausible que cometa un novato en la API.

Peter Taylor
fuente
1
Incluso si OrderBy modifica hipotéticamente el objeto, ¿esa llamada realmente ordenaría la lista al azar? Como alguien que no está familiarizado con .NET, mi primera suposición fue que, dado que rng.Next()solo se llama una vez, la matriz se ordenaría por una constante, lo que no produciría ningún cambio (o un cambio que dependa solo del algoritmo de clasificación).
Brilliand
1
@Brilliand El argumento pasado a OrderBy no es un valor estático, se ejecuta cada vez que se ordena un elemento, y en este caso devuelve valores aleatorios sin comparar ningún valor. Realmente funcionaría correctamente si la línea fueranames = names.OrderBy(name => rng.Next());
user3188175
1
El =>indica que esta es una expresión lambda de C # (cierre).
Snowbody
44

Potencia Shell

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

Esto siempre saldrá John.

$nameses un System.Collections.Hashtableque no tiene una Lengthpropiedad. A partir de PowerShell v3, Length(y también Count) se puede usar como una propiedad en cualquier objeto. Si un objeto no tiene la propiedad, regresará 1cuando el objeto no sea nulo, de lo contrario, regresará 0. Entonces, en mi respuesta, se $names.Lengthevalúa como 1 y random -maximum 1siempre devuelve 0 ya que el máximo es exclusivo.

Rynant
fuente
42

Q

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

Q siempre inicializa su semilla de número aleatorio con el mismo valor.

skeevey
fuente
8
así que básicamente no es nada aleatorio
Sam Creamer
3
@SamCreamer El propósito de la pregunta es hacer que la salida no sea aleatoria. Pero esto parece aleatorio, así que definitivamente se ajusta a la factura
Cruncher
44
Lo siento, quise decir que los números aleatorios de Q no son tan aleatorios, esta pregunta ciertamente cumple con los criterios. ¡No quise parecer de esa manera!
Sam Creamer
Sí, ¿entonces tienes que encontrar tu propia forma de generar una semilla aleatoria cada vez que quieras usar rand? Suena ... útil.
DLeh
1
Puede establecer la semilla aleatoria manualmente muy fácilmente ... inicie el intérprete con la -S 1234opción o hágalo \S 1234desde el 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";

Imprime: Person X is buying: Jeff(donde X es de 0-4)

Abusar un poco del contexto escalar. @index = int(rand() * 5)coloca un número entero aleatorio de 0 a 4 en la posición 0 de la @indexlista. Al imprimir la matriz, imprime correctamente el entero aleatorio en @index, pero cuando se usa como índice de matriz en$people[@index] @index usa el contexto escalar, lo que le da el valor del tamaño de la lista, es decir 1.

Suficientemente interesante, @people[@index] hace que se indexe correctamente.

Curiosamente, @people[@index]hay un hash slice en Perl, por lo que @indexse evalúa en el contexto de la lista; en este caso, es una lista de entrada única y por eso funciona correctamente

Allen G
fuente
Entonces, en términos de C (++), ¿hay una conversión implícita de la lista a escalar porque cuando se indexa, se espera un escalar?
iFreilicht
@iFreilicht Correcto. En Perl, las expresiones se pueden evaluar como una lista o como un escalar, dependiendo de dónde aparezcan. Como resultado, la misma expresión puede significar cosas diferentes, dependiendo del contexto. Una variable de lista (es decir, una variable con el @prefijo), en "contexto de lista", se interpreta como todos sus elementos, pero en "contexto escalar", es un escalar igual al número total de elementos en la lista. Por lo tanto, dentro de la cadena, la variable de lista tiene contexto de lista y se interpola, y obtenemos Person X is buying. Pero como un índice de matriz, obtiene un contexto escalar y se interpreta como 1.
Allen G
3
El problema con esto es que cuando un programador de Perl ve my @index = ..., inmediatamente se pregunta "WTF ?!".
derobert
@derobert, ¿por qué te preguntas? Ves código así bastante a menudo ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;etc.
Matthias
@Matthias porque la línea es para elegir y almacenar un solo valor, y en lugar de un escalar se está almacenando en una matriz.
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]);

Es siempre recoge Julie.

Tiene corchetes dentro de los corchetes, y el operador de coma devuelve el valor de su operando correcto.
También es muy fácil perderse. Lo he extrañado antes en código real .

Cepillo de dientes
fuente
Esto es encantador Finalmente, un uso para ese terrible, terrible operador.
Keen
55
La coma en ese contexto es técnicamente un operador, en lugar de un separador. ecma-international.org/ecma-262/5.1/#sec-11.14 Y es terrible. A menos que desee que su código sea difícil de leer. Como haces aquí. Entonces, felicitaciones.
Keen
2
@Cory Sí, estoy de acuerdo, aunque lo uso todo el tiempo para Code Golf con expresiones de función (por ejemplo (a,b)=>(a=b[0],b)). He aclarado mi respuesta.
Cepillo de dientes
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]);
        }
    }
}

El truco es que el método new Random().NextDouble()devuelve un doble entre 0 y 1. Al aplicar Math.Floor()este valor, siempre será 0.

Knerd
fuente
24
No soportó mi mirada rápida. ;)
Martin Ender
1
@TimS. ¿como eso? : P
Knerd
2
+1, Mucho mejor: sé lo que realmente estás haciendo, pero podría engañar a alguien que no esté demasiado familiarizado con la API.
Tim S.
1
No se sobre esto. Si va a especificar una semilla, ¿por qué no usar la forma correcta de conseguir un int "al azar":var random = new Random(5); var id = random.NextInt(5);
clcto
2
@clcto En mi opinión, incluirlo dos veces es más probable que haga que alguien haga una doble toma, pregunte por qué y vea el problema. Incluirlo una vez, y luego incluir código innecesario después, da un poco de redirección / falta de supervisión. Bonificación: si alguien corrige uno de los errores, existe otro.
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]);

Insinuación:

Generar semilla desde GUID. Los guías tienen una probabilidad de colisión de 4 × 10−10. Súper aleatorio.

Responder:

Al menos cuando lo usas Guid.NewGuid(), ¡vaya! (Manera disimulada para hacer semilla siempre 0). También no tiene sentido (int) para la mala dirección.

Nathan Cooper
fuente
La otra forma en que podría hacerlo es AddRangeconfundirme Concatal agregar nombres a a List<string>. Se me ocurrió tener un Hashset con un IEqualityComparer astuto, pero sería demasiado inusual. En mi crédito, no había muchas (si las hubo) respuestas basadas en semillas cuando publiqué esto.
Nathan Cooper
Supongo que tuvo la misma idea que yo, pero fue un poco más rápido y lo hizo un poco más difícil de ver. +1!
tsavinho
77
Sembrar el generador de números aleatorios es un truco obvio, pero aquí lo has escondido brillantemente. Trabajo encantador.
TRiG
18

bash / coreutils

Esto se toma casi al pie de la letra de un guión que escribí con un propósito similar.

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

Incluso olvidar usar una R mayúscula es un error que ocasionalmente cometí en los guiones de la vida real.

kasperd
fuente
3
¿podrías dar una mejor explicación? Su actual es realmente corto y no es útil para alguien que no está realmente familiarizado con bash.
iFreilicht
66
-respecifica el orden inverso (lexicográfico), por lo que Steve siempre será elegido. Podría verse como un error tipográfico inocente de -Rclasificación aleatoria
Max
3
¡Es un buen recordatorio para no confiar en los comentarios, sino para leer cuidadosamente el código!
TecBrat
16

Rubí

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

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

Esto funcionaría correctamente con sort_by, pero sortespera una función de comparación que funcione como <=>. El resultado de rand () siempre será positivo, por lo que siempre producirá resultados equivalentes siempre que el sortalgoritmo de su implementación de Ruby sea ​​determinista. Mi Ruby 1.9.3 siempre saca a Julie.

histocrat
fuente
12

Rubí

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

puts names[rand() % 5]

rand() sin argumentos produce un flotante aleatorio entre 0 y 1. Por lo tanto, el módulo 5 no hace nada, y cuando se divide en una matriz con un argumento flotante, Ruby simplemente lo redondea hacia abajo, por lo que esto siempre devuelve a John.

histocrat
fuente
11

Perl

¡tres srands lo harán tres veces más aleatorio!

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

explicación

no hay $ RANDOM en perl, es una variable indefinida. el código siempre devolverá el primer elemento de la lista: bebidas en John :)

editar:

Después de revisar el código, uno de los cinco chicos decidió arreglar el error obvio, produciendo el siguiente 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!";

¿Puedes decir quién lo hizo simplemente mirando el código?

explicación:

en Perl, $#arraydevuelve el índice del último elemento; ya que se basan en cero arrays, da una referencia a una matriz con cinco elementos, $#$aref_peopleserá 4.
randdevuelve un número aleatorio mayor o igual a cero y menor que su parámetro, por lo que nunca volverá 4, lo que significa que Julie nunca comprará bebidas :)

perl chino goth
fuente
1
$RANDOMes una característica real en bash, ksh y zsh (pero no en perl).
kernigh
10

Pitón

Todo el mundo sabe que no puedes confiar en la aleatoriedad en un espacio de muestra tan pequeño; para hacerlo verdaderamente aleatorio, he abandonado el método anticuado de elegir un nombre de una lista, y en su lugar, mi programa deletreará un nombre completamente aleatorio. Como la mayoría de los nombres en la oficina tenían 4 letras, nos conformaremos con eso.

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, hice un trabajo de preparación para asegurarme de elegir la semilla correcta.

Tal
fuente
15
Sembrar el número aleatorio generado con una constante es demasiado obvio ...
Restablecer Monica
@BrendanLong Definitivamente levantaría las cejas. La gente querría probarlo para asegurarse de que sea aleatorio. Y cuando no es así, adivina quién está comprando bebidas.
JFA
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] );
}

Lo siento Jeff!

Después de algunas iteraciones r == 1 mod 5, debido a las matemáticas. Moralidad: no escribas tu propio PRNG si eres malo en matemáticas. :)

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

El tamaño del vector es en realidad 1 debido al paréntesis utilizado en la lista de inicializadores. El operador de coma descartará todos los nombres y devolverá el último, por lo tanto, el comprador siempre es Roy.

tomasz
fuente
10

Scala

Sé que mis usuarios serán escépticos, ¡así que he incluido una prueba de que mi aleatoriedad es 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
  }

}

Un ejemplo de ejecución:

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 alguien tenga mucha suerte, John siempre comprará las bebidas.

La "prueba" de aleatoriedad se basa en el hecho de que rand(1, 4) * rand(1, 4) % 5todavía se distribuye uniformemente entre 1 y 4, inclusive. Pero rand(1, 5) * rand(1, 5) % 6es degenerado. Existe la posibilidad de obtener un 0, que luego haría que el resultado final sea 0 independientemente del resto de la "aleatoriedad".

Joe K
fuente
10

Javascript (con Underscore.js )

Como javascript no tiene un shuffle integrado, utilizaremos Underscore.js

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

_.shuffle devuelve la matriz aleatoria , no se modifica en su lugar como Array.prototype.sort () , lo siento John

Kristoffer Sall-Storgaard
fuente
9

JavaScript

Segundo intento, este es un poco más complicado:

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

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

La argumentsvariable es accesible localmente para las funciones y es una matriz de todos los argumentos pasados ​​a la función. Al usar nombres simples y pasar una matriz a la función en sí, puede suponer que no estamos tomando la longitud de la matriz, sino de hecho la longitud de la lista de argumentos (que es 1). Esto se puede ejecutar aún mejor utilizando caracteres especiales o un tipo de fuente.

thomaux
fuente
Este no fue el más difícil de detectar. Cualquiera que haya construido una Nfunción arbitraria -ary en JavaScript sabe acerca de la argumentsvariable.
Conor O'Brien el
8

C ++

Para ser justos, debemos realizar muchos, muchos ensayos y elegir a quien se seleccione con mayor frecuencia.

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

¿Cuál es el valor de 1<<31? Lo siento John

mullido
fuente
La respuesta a tu pregunta de spoiler es UB. Estoy indeciso si eso hace que sea mejor o peor.
nwp
@nwp Bueno, claro, pero tiene en cualquier lugar que int es el complemento de 2 de 32 bits, que parece ser el caso incluso en 64 bits (con gcc). Sin embargo, no he probado en Clang.
esponjoso
No, no se mantiene en ningún lugar donde un int es 32, pero 2 es complemento. El valor de 1 << 31 no está definido. Sin embargo, tienes suerte, el comportamiento indefinido hace que el compilador elija lo que se siente y, dado que está hecho para la velocidad, simplemente decidirá no hacer nada, lo que resulta ser lo que quieres.
nwp
@nwp 1<<31 == 0x80000000no importa qué, por la definición misma <<y en el complemento de 2 de 32 bits, eso es INT_MIN. ¿Quizás estás pensando en 1<<32cuál puede o no == 0? (Porque en x86, 1<<32generalmente se evalúa a 1 ...)
esponjoso
@nwp En realidad, está definido por la implementación. Ahora, si estuviéramos hablando de C, entonces sería indefinido.
Stuart Olsen
7

T-SQL (2008+)

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

Explicación:

En MS SQL Server, RAND()solo se evalúa una vez por ejecución. A cada nombre siempre se le asigna el mismo número, dejando el pedido original. John es el primero. Es una mierda para John.

Mejora sugerida:

T-SQL puede producir números aleatorios por fila de buena calidad con RAND(CHECKSUM(NEWID())).

cómodamentedrei
fuente
Creo que ORDER BY NEWID () será suficiente (no es necesario 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()es para propósitos de tiempo, os.time()es lo que se debe usar math.randomseedpara un buen RNG. Lamentablemente, Julie siempre compra (al menos en mi computadora).

Kyle Kanos
fuente
math.random()sin argumentos también devuelve un número en el rango [0,1). -1 por no atrapar eso.
mniip
@mniip: ¡Realmente merecido también! Ya lo arreglé.
Kyle Kanos
6

Idiomatic C ++ 11

Cuando se trata de bebidas, es especialmente importante estar al día con los últimos estándares y estilos de codificación; Este es un gran ejemplo de un selector de nombres C ++ 11 altamente eficiente y compatible con modismos.

Se siembra desde el reloj del sistema y genera la semilla junto con el nombre para la verificación 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
}

Prueba esto en vivo: http://ideone.com/KOet5H

Ok, este es un código bastante bueno en general; hay muchas pistas falsas para hacer que mires demasiado de cerca el código para notar lo obvio: que el RNG nunca se siembra :) En este caso seedes solo un número entero, y aunque parece que enginese pasa como un parámetro a un función de siembra, en realidad solo se ignora. La variable semilla realmente se establece desde el reloj, por lo que puede aparecer al final junto con el nombre para agregar insulto a la lesión, pero siempre será Steve quien compre las bebidas.

Alboroto
fuente
1
Me mata que no use una lista de inicializadores para los nombres. Por lo menos, definitivamente ha logrado proporcionar código que se siente demasiado diseñado. No puedo decir si es por el "cumplimiento" o todos los comentarios de ruido: P
vmrob
6

JavaScript

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

Bueno, lo siento, Math.randomno toma un parámetro y siempre devolverá un número de [0, 1). ¡Aún así, es una función variada feliz y no se queja de argumentos!

Bergi
fuente
5

Pitón

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 (aleatorio) da una cadena constante; no es un valor aleatorio

QuadrExAtt
fuente
66
Una nota algo irrelevante: si está utilizando Python 3.2 o posterior, el segundo argumento random.seed()debe ser 2(el predeterminado). Si pasa version=1, el hash()de la cadena se usará como una semilla en lugar de la cadena completa, y debido a que Python siembra aleatoriamente los valores hash de las cadenas que comienzan en 3.2, obtendrá un nombre realmente aleatorio.
Blacklight Shining
5

Perl

¡Es mejor que Emma no olvide su bolso! Corre debajo stricty 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.

Explicación aquí .

Zaid
fuente
Perl 5.18 cambió esto un poco, al introducir la aleatorización de claves hash (para evitar ataques de complejidad de colisión hash).
Konrad Borowski
4

JavaScript

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

Los |0resultados en 0 todo el tiempo, pero parece que está haciendo algún otro redondeo.

Mate
fuente
Me gusta. Aunque lo haría parseInt(Math.random(0, 4))y tal vez agregaría comentarios como: Math.randomdevuelve un doble, así que conviértalo primero en un número entero
Claudiu
55
El truco es que en realidad Math.randomno le importan nuestros escasos parámetros. Elige los números a su manera. El |0está redondeando correctamente el resultado inesperado, por lo que no es una fuente de ningún truco.
Keen
|0es muy obvio para algunos (todos nosotros muy probablemente), pero apuesto a que hay muchos que no tienen idea de lo que hace. Ese es el grupo en el que confiaba engañando.
Matt
3
@ Matt Quiero decir que |0, si sabes lo que hace, parece que se está redondeando hacia abajo, y se está redondeando hacia abajo, por lo que no es un engaño. (Y si alguien no tiene idea de lo que |0hace, entonces no sirve de nada el código engañoso; simplemente puede decirle lo que quiera que crea). En cambio, el comportamiento inesperado en su respuesta se basa en el hecho de que Math.random(0,4)es funcionalmente idéntico a Math.random(), porque Math.randomno usa parámetros.
Keen
4

J

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

Pobre Julie ... Trivia: esta podría haber sido la J más limpia que he escrito ...

Este código es realmente correcto, excepto por una cosa. ?.es el rng uniforme: ?.5siempre devolverá 4. ?5habría sido correcto.

ɐɔıʇǝɥʇuʎs
fuente