Script acak yang sebenarnya bukan acak


106

Sebagai lelucon kecil di kantor seseorang menginginkan sebuah skrip yang secara acak mengambil nama, dan mengatakan orang itu akan membuat minuman.

Sebut saja orang-orang seperti John, Jeff, Emma, ​​Steve dan Julie.

Saya pikir itu akan lucu untuk membuat skrip yang tampak acak secara sekilas, tetapi sebenarnya selalu memberikan orang yang sama sebagai output (Terserah Anda yang Anda pilih).

Jawaban dengan suara terbanyak menang setelah seminggu

Dan pemenangnya adalah....

Paul R dengan (saat ini) 158 suara.

Jawabannya sangat bagus, dan jika ada orang lain yang memiliki ide lain yang belum diposting, silakan tambahkan, saya suka membacanya.



6
@AstroCB salah satu favorit saya. Tepat di belakang meja bobby.
Cruncher

50
Sepertinya akan lebih licik jika itu acak, kecuali untuk tidak memilih satu orang.
Brendan Long

6
@AstroCB satu ini juga fantastis: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb

3
Saya membaca halaman pertama: sebagian besar jawaban selalu memilih John, tertinggi ke-2 adalah Julie, Jeff jarang dipilih dan Steve dengan 1. Bahkan Ray dipilih oleh satu tetapi tidak ada yang memilih Emma. Moral dari cerita ini: ketika berdiri dalam antrean untuk memutuskan secara acak siapa yang akan membeli minuman, beri nama diri Anda Emma.
Variabel yang

Jawaban:


171

C

Sangat penting untuk memutuskan siapa yang membeli secepat mungkin, agar tidak membuang waktu minum yang berharga - maka C adalah pilihan yang jelas untuk mendapatkan kinerja maksimal:

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

Penjelasan:

Ini akan bekerja dengan baik jika ada break;setelah setiap kasus dalam pernyataan switch. Namun demikian, setiap kasing "jatuh" ke yang berikutnya, sehingga Julie yang malang selalu membeli minuman.


17
+1 untuk kinerja - jauh lebih cepat daripada menggulirkan dadu fisik! ;)
Jwosty

16
Saya sedang berpikir untuk mengoptimalkannya lebih lanjut, mungkin dengan SIMD atau GPGPU, hanya untuk mendapatkan kinerja yang lebih sedikit. ;-)
Paul R

7
Benar-benar nyata dapat diterapkan. Tidak ada yang akan mempertanyakan bahwa itu adalah kecelakaan sedikit pun.
iFreilicht

5
Apakah hanya saya atau ini terlalu jelas untuk dilihat?
Alvin Wong

3
@ AlvinWong saya tidak segera menyadarinya. Kemudian lagi, saya tidak menggunakan C secara teratur, atau bahasa lain apa pun yang diturunkan dari BCPL.
Rhymoid

164

PHP

Tidak bisa melepaskan ini, jadi ini yang lain:

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

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

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

Ini sebenarnya tidak dijamin untuk menghasilkan john, tetapi kemungkinannya sangat bagus. PHP akan dengan senang hati mengambil apa pun yang ditawarkan oleh / dev / random untuk melihat bahwa itu (mungkin) tidak dapat menguraikannya dan menghasilkan angka 0 yang sangat masuk akal. Setelah semua, mengingatkan programmer untuk kesalahan potensial dianggap dosa mematikan di PHP.


25
Anda harus mencintai PHP - dan bahkan lebih baik lagi, terkadang akan jarang memilih orang lain. Jadi, jika Anda beruntung, itu akan terasa sedikit bias pada awalnya
Falco

142
+1000 untuk "... mengingatkan programmer tentang kesalahan potensial dianggap dosa mematikan di PHP."
jsedano


85

Haskell

Terlalu transparan jika selalu mengembalikan nama yang sama jadi coba yang berikut ini

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

Setiap kali Anda menginginkannya acak:

[~]$ runghc prog.hs
Shuffling
Steve

[~]$ runghc prog.hs
Shuffling
Julie

Dan untuk target malang Anda:

[~]$ runhugs prog.hs
Shuffling
John

[~]$ runhugs prog.hs
Shuffling
John

Pelukan hanya menerapkan multitasking kooperatif, sehingga rotateutas tidak akan pernah berjalan


24
Itu jahat!
Daenyth

8
Terasa seperti memotret dadu yang belum berhenti bergerak.
Vi.

1
@ Vi. Itu analogi yang bagus. Untungnya penggunaan MVars menjamin bahwa gambar tidak akan buram. :)
monocell

@monocell Nah, secara teknis, bahkan foto dari objek yang bergerak bisa jelas.
ghosts_in_the_code

75

Bash - kesederhanaan maksimum

Contoh yang sangat sederhana - mari kita hindari masalah dengan melakukannya dengan cara buku teks. Jangan lupa untuk menyemai generator dari jam sistem untuk hasil yang bagus!

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

Ini bergantung pada pengguna yang tidak tahu apa $SECONDSsebenarnya yang dibangun; ia mengembalikan jumlah detik sejak shell saat ini dimulai. Seperti dalam skrip, shell selalu dimulai nol detik yang lalu, jadi generator selalu diunggulkan 0dan Julie selalu membeli bir.

Bonus:

Yang ini bertahan dengan cukup cermat; Jika Anda memasukkan kode yang sama pada commandline alih-alih dalam skrip, itu akan memberikan hasil acak, karena $SECONDSakan mengembalikan lama waktu shell interaktif pengguna telah berjalan.


9
\ o / Berarti !!! Sangat jahat!!! $SECONDSftw! \ o /
yeti

Apa yang terjadi jika Anda sourceini, bukan hanya menjalankannya? Akankah shebang masih memicu shell baru atau sesuatu?
jpmc26

1
@ jpmc26: jika Anda menjalankannya dengan sourceitu persis sama seperti jika Anda mengetik sendiri perintah pada commandline; #! / bin / bash adalah komentar sehingga diabaikan. Ini berlaku untuk semua skrip.
Kerusuhan

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

Ini mungkin tidak menipu orang-orang yang terbiasa dengan .Net API, tetapi orang-orang yang tidak mengetahuinya mungkin percaya bahwa OrderBymemodifikasi objek yang Anda panggil, dan itu adalah kesalahan yang masuk akal untuk dibuat oleh pemula.


1
Bahkan jika OrderBy memodifikasi objek secara hipotetis, apakah panggilan itu akan mengurutkan daftar secara acak? Sebagai seseorang yang tidak terbiasa dengan .NET, tebakan pertama saya adalah karena rng.Next()hanya dipanggil sekali, array akan diurutkan berdasarkan konstanta, sehingga tidak ada perubahan (atau perubahan yang hanya bergantung pada algoritma pengurutan).
Brilliand

1
@Brilliand Argumen yang diteruskan ke OrderBy bukan nilai statis, dijalankan setiap kali elemen diurutkan, dan dalam hal ini mengembalikan nilai acak tanpa membandingkan nilai apa pun. Ini benar-benar akan berfungsi dengan benar jika salurannya adalahnames = names.OrderBy(name => rng.Next());
user3188175

1
Yang =>menunjukkan bahwa ini adalah ekspresi C # lambda (penutupan).
Snowbody

44

PowerShell

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

Ini akan selalu ditampilkan John.

$namesadalah System.Collections.Hashtableyang tidak memiliki Lengthproperti. Dimulai dengan PowerShell v3, Length(dan juga Count) dapat digunakan sebagai properti pada objek apa pun. Jika suatu objek tidak memiliki properti, itu akan kembali 1ketika objek itu tidak nol, kalau tidak itu akan kembali 0. Jadi dalam jawaban saya, $names.Lengthevaluasi sebagai 1, dan random -maximum 1selalu mengembalikan 0 karena maksimum eksklusif.


42

Q

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

Q selalu menginisialisasi seed number acaknya dengan nilai yang sama.


8
jadi pada dasarnya itu tidak acak sama sekali
Sam Creamer

3
@ SamCreamer Tujuan dari pertanyaan ini sangat banyak untuk membuat output non-acak. Tapi ini memang terlihat acak sehingga pasti sesuai dengan tagihan
Cruncher

4
Maaf, maksud saya angka acak Q tidak acak, pertanyaan ini tentu memenuhi kriteria. Tidak bermaksud bertemu seperti itu!
Sam Creamer

Ya, jadi Anda harus menemukan cara Anda sendiri untuk menghasilkan benih acak setiap kali Anda ingin menggunakan rand? Kedengarannya ... bermanfaat.
DLeh

1
Dapat mengatur benih acak secara manual dengan sangat mudah ... mulai penerjemah dengan -S 1234opsi atau lakukan \S 1234dari penerjemah
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";

Cetakan: Person X is buying: Jeff(di mana X adalah dari 0-4)

Menyalahgunakan konteks skalar sedikit. @index = int(rand() * 5)menempatkan integer acak dari 0 - 4 di posisi ke-0 dari @indexdaftar. Saat mencetak array, ia benar mencetak bilangan bulat acak di @index, tetapi ketika menggunakan sebagai indeks array $people[@index], @index menggunakan konteks skalar, memberikan nilai ukuran daftar, yaitu 1.

Cukup menarik, @people[@index]membuatnya indeks dengan benar.

Yang cukup menarik @people[@index]adalah potongan hash di Perl, jadi @indexdievaluasi dalam konteks daftar; dalam hal ini, ini adalah daftar entri tunggal dan itulah sebabnya ia bekerja dengan benar


Jadi dalam istilah C (++), ada konversi implisit dari daftar ke skalar yang terjadi karena ketika pengindeksan, skalar diharapkan?
iFreilicht

@ iFreilicht Benar. Dalam Perl, ekspresi dapat dievaluasi sebagai daftar atau sebagai skalar, tergantung di mana mereka muncul. Akibatnya, ekspresi yang sama dapat berarti hal yang berbeda, tergantung pada konteksnya. Variabel daftar (yaitu variabel dengan @awalan), dalam "konteks daftar," ditafsirkan sebagai semua elemennya, tetapi dalam "konteks skalar," adalah skalar yang sama dengan jumlah total elemen dalam daftar. Oleh karena itu, di dalam string, variabel daftar memiliki konteks daftar dan diinterpolasi, dan kita dapatkan Person X is buying. Tetapi sebagai indeks array, ia mendapatkan konteks skalar, dan ditafsirkan sebagai 1.
Allen G

3
Masalah dengan ini adalah bahwa ketika seorang programmer Perl melihat my @index = ..., ia langsung bertanya-tanya "WTF ?!".
derobert

@derobert, Mengapa Anda ingin tahu? Anda melihat kode seperti itu cukup sering ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;dll.
Matthias

@Matthias karena barisnya adalah untuk mengambil dan menyimpan nilai tunggal, dan bukannya skalar, ini disimpan dalam array.
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]);

Itu selalu memilih Julie.

Memiliki tanda kurung di dalam tanda kurung siku, dan operator koma mengembalikan nilai operan yang tepat.
Ini juga sangat mudah untuk dilewatkan. Saya telah melewatkannya sebelumnya dalam kode nyata .


Ini menyenangkan. Akhirnya, penggunaan untuk operator yang mengerikan itu.
Tertarik

5
Koma dalam konteks itu secara teknis adalah operator, bukan pemisah. ecma-international.org/ecma-262/5.1/#sec-11.14 Dan itu mengerikan. Kecuali Anda ingin kode Anda sulit dibaca. Seperti yang Anda lakukan di sini. Jadi, pujian.
Tertarik

2
@Cory Ya, saya setuju - meskipun saya menggunakannya sepanjang waktu untuk Code Golf dengan ekspresi fungsi (misalnya (a,b)=>(a=b[0],b)). Saya sudah mengklarifikasi jawaban saya.
Sikat gigi

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

Caranya adalah, metode ini new Random().NextDouble()mengembalikan dua kali lipat antara 0 dan 1. Dengan menerapkan Math.Floor()nilai ini, itu akan selalu menjadi 0.


24
Itu tidak tahan sekilas. ;)
Martin Ender

1
@TIM. seperti itu? : P
Knerd

2
+1, Jauh lebih baik - Saya tahu apa yang sebenarnya Anda lakukan, tetapi itu bisa menipu seseorang yang tidak terlalu mengenal API.
Tim S.

1
Saya tidak tahu tentang ini. Jika Anda akan menentukan benih, mengapa tidak menggunakan cara yang tepat untuk mendapatkan int "acak":var random = new Random(5); var id = random.NextInt(5);
clcto

2
@ clcto Menurut saya, memasukkannya dua kali lebih mungkin membuat seseorang melakukan pengambilan ganda, bertanya mengapa, dan melihat masalahnya. Termasuk sekali, dan kemudian termasuk kode yang tidak perlu sesudahnya, memberikan sedikit pengalihan / underhandedness. Bonus: jika seseorang memperbaiki salah satu bug, yang lain ada.
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]);

Petunjuk:

Hasilkan benih dari GUID. Panduan memiliki 4 × 10-10 kemungkinan tabrakan. Super acak.

Menjawab:

Setidaknya saat Anda menggunakan Guid.NewGuid(), whoops! (Cara licik untuk membuat benih selalu 0). Juga tidak berguna (int) untuk penyesatan.


Cara lain saya mungkin melakukannya, adalah menjadi AddRangekacau Concatketika menambahkan nama ke a List<string>. Apakah terpikir oleh saya untuk memiliki Hashset dengan IEqualityComparer yang licik, tetapi itu akan menjadi terlalu tidak biasa. Dalam kredit saya, tidak ada banyak (jika ada) jawaban berbasis benih ketika saya memposting ini.
Nathan Cooper

Saya kira Anda memiliki ide yang sama dengan saya, tetapi Anda sedikit lebih cepat dan membuatnya lebih sulit untuk dilihat. +1!
tsavinho

7
Menyemai generator angka acak adalah trik yang jelas, tetapi Anda telah menyembunyikannya dengan cemerlang di sini. Kerja yang bagus.
TRiG

18

bash / coreutils

Ini diambil hampir kata demi kata dari naskah yang saya tulis untuk tujuan yang sama.

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

Bahkan lupa menggunakan huruf besar R adalah kesalahan yang sesekali saya buat dalam skrip kehidupan nyata.


3
dapatkah Anda memberikan penjelasan yang lebih baik? Yang Anda miliki saat ini sangat singkat dan tidak membantu seseorang yang tidak terlalu mengenal bash.
iFreilicht

6
-rmenentukan jenis pembalikan (leksikografis), jadi Steve akan selalu dipilih. Itu bisa dilihat sebagai kesalahan ketik -Runtuk jenis acak
Max

3
Itu pengingat yang baik untuk tidak mempercayai komentar, tetapi untuk membaca kode dengan cermat!
TecBrat

16

Rubi

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

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

Ini akan bekerja dengan benar sort_by, tetapi sortmengharapkan fungsi perbandingan yang berfungsi seperti <=>. rand () hasilnya akan selalu positif, sehingga akan selalu menghasilkan hasil yang setara asalkan sortalgoritma implementasi Ruby Anda bersifat deterministik. Ruby 1.9.3 saya selalu menampilkan Julie.


12

Rubi

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

puts names[rand() % 5]

rand() tanpa argumen menghasilkan float acak antara 0 dan 1. Jadi modulo 5 tidak melakukan apa-apa, dan ketika mengiris menjadi array dengan argumen float, Ruby hanya membulatkannya ke bawah, jadi ini selalu mengembalikan John.


11

Perl

three srands akan membuatnya tiga kali lebih acak!

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

penjelasan

tidak ada $ ACAK di perl, ini adalah variabel yang tidak ditentukan. kode akan selalu mengembalikan elemen pertama dari daftar - minuman di John :)

sunting:

setelah melalui kode, salah satu dari lima orang telah memutuskan untuk memperbaiki kesalahan yang jelas, menghasilkan program berikut:

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

dapatkah Anda memberi tahu siapa yang melakukannya hanya dengan melihat kode?

penjelasan:

di Perl, $#arraymengembalikan indeks elemen terakhir; karena array berbasis nol, diberikan referensi ke array dengan lima elemen, $#$aref_peopleakan menjadi 4.
randmengembalikan angka acak lebih besar atau sama dengan nol dan kurang dari parameternya, sehingga tidak akan pernah kembali 4, yang secara efektif berarti Julie tidak akan pernah membeli minuman :)


1
$RANDOMadalah fitur nyata dalam bash, ksh dan zsh (tetapi tidak dalam perl).
kernigh

10

Python

Semua orang tahu bahwa Anda tidak bisa mempercayai keacakan dalam ruang sampel sekecil ini; untuk membuatnya benar-benar acak, saya telah meninggalkan metode usang memilih nama dari daftar, dan sebaliknya program saya akan mengeja nama yang sepenuhnya acak. Karena sebagian besar nama di kantor memiliki 4 huruf, kami akan setuju untuk itu.

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)

Secara alami, saya melakukan beberapa persiapan untuk memastikan saya memilih benih yang tepat.


15
Melihat angka acak menghasilkan dengan konstanta terlalu jelas ..
Brendan Long

@ BrendanLong Itu pasti akan menaikkan alis. Orang ingin mengujinya untuk memastikannya acak. Dan ketika tidak, tebak siapa yang membeli minuman.
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] );
}

Maaf, Jeff!

Setelah beberapa iterasi r == 1 mod 5, karena matematika. Moralitas: jangan menulis PRNG Anda sendiri jika Anda buruk dalam matematika. :)


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

Ukuran vektor sebenarnya 1 karena tanda kurung yang digunakan dalam daftar penginisialisasi. Operator koma akan membuang semua nama dan mengembalikan yang terakhir, maka pembeli selalu Roy.


10

Scala

Saya tahu pengguna saya akan skeptis, jadi saya telah menyertakan bukti bahwa keacakan saya benar-benar adil!

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
  }

}

Satu contoh dijalankan:

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

Kecuali orang lain sangat beruntung, John akan selalu membeli minuman.

"Bukti" keacakan bergantung pada fakta yang rand(1, 4) * rand(1, 4) % 5masih merata antara 1 dan 4, inklusif. Tapi rand(1, 5) * rand(1, 5) % 6merosot. Ada kemungkinan Anda mendapatkan 0, yang kemudian akan membuat hasil akhir 0 terlepas dari sisa "keacakan".



9

JavaScript

Percobaan kedua, yang ini sedikit rumit:

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

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

The argumentsvariabel lokal dapat diakses untuk fungsi dan sebuah array dari semua argumen dilewatkan ke fungsi. Dengan menggunakan penamaan sederhana dan meneruskan dalam array ke fungsi itu sendiri, Anda dapat menipu bahwa kita tidak mengambil panjang array, tetapi pada kenyataannya panjang daftar argumen (yaitu 1). Ini bisa lebih baik dieksekusi dengan menggunakan karakter khusus atau jenis font.


Ini bukan yang paling sulit dikenali. Siapa pun yang telah membangun fungsi arbitrer Ndalam JavaScript tahu tentang argumentsvariabel.
Conor O'Brien

8

C ++

Agar adil kita harus menjalankan banyak, banyak cobaan dan memilih siapa yang paling sering dipilih.

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

Apa nilainya 1<<31? Maaf, John.


Jawaban untuk pertanyaan spoiler Anda adalah UB. Saya ragu apakah itu membuat lebih baik atau lebih buruk.
nwp

@ nwp Yah, tentu saja, tapi itu tetap di mana int adalah komplemen 32-bit 2, yang tampaknya menjadi kasus bahkan pada 64-bit (dengan gcc). Saya belum menguji di dentang, meskipun.
lembut

Tidak, itu tidak berlaku di mana pun int adalah 32-tapi pelengkap 2. Nilai 1 << 31 tidak ditentukan. Anda beruntung, perilaku yang tidak terdefinisi membuat kompiler memilih apa pun rasanya dan karena dibuat untuk kecepatan, ia hanya akan memutuskan untuk tidak melakukan apa-apa, yang merupakan apa yang Anda inginkan.
nwp

@ nwp 1<<31 == 0x80000000tidak peduli apa, dengan definisi <<, dan pada komplemen 32-bit 2, itu INT_MIN. Apakah Anda mungkin memikirkan 1<<32yang mungkin atau tidak == 0? (Karena pada x86, 1<<32biasanya bernilai 1 ...)
fluffy

@ nwp Sebenarnya ini adalah implementasi yang ditentukan. Sekarang jika kita berbicara tentang C, maka itu tidak akan ditentukan.
Stuart Olsen

7

T-SQL (2008+)

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

Penjelasan:

Di MS SQL Server, RAND()hanya mengevaluasi sekali per eksekusi. Setiap nama selalu mendapat nomor yang sama, meninggalkan pesanan awal. John yang pertama. Menyebalkan untuk John.

Perbaikan yang disarankan:

T-SQL dapat menghasilkan kualitas acak dengan angka acak per baris RAND(CHECKSUM(NEWID())).


Saya pikir ORDER BY NEWID () akan mencukupi (tidak perlu 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()adalah untuk tujuan waktu, os.time()adalah apa yang harus digunakan math.randomseeduntuk RNG yang baik. Sayangnya, Julie selalu membeli (setidaknya di komputer saya).


math.random()tanpa argumen juga mengembalikan angka dalam kisaran [0,1). -1 untuk tidak menangkap itu.
mniip

@niip: Benar-benar layak juga! Saya sudah memperbaikinya sekarang.
Kyle Kanos

6

Idiomatik C ++ 11

Ketika minuman terlibat, sangat penting untuk mendapatkan informasi terbaru tentang standar dan gaya pengkodean terbaru; ini adalah contoh yang bagus dari pemilih nama C ++ 11 yang sangat efisien dan sesuai idiom.

Ini diunggulkan dari sistem jam, dan output benih bersama dengan nama untuk verifikasi setiap kali.

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

Coba ini langsung: http://ideone.com/KOet5H

Ok jadi ini sebenarnya kode yang cukup bagus secara keseluruhan; ada banyak ikan haring merah untuk membuat Anda melihat terlalu dekat pada kode untuk melihat yang jelas - bahwa RNG tidak pernah benar-benar diunggulkan :) Dalam hal seedini hanyalah bilangan bulat, dan sementara itu sepertinya enginedilewatkan sebagai parameter ke fungsi seeding, itu sebenarnya hanya diabaikan. Variabel seed benar-benar diatur dari waktu, jadi itu bisa menjadi output di akhir bersama dengan nama untuk menambah penghinaan pada cedera, tetapi itu akan selalu menjadi Steve yang membeli minuman.


1
Itu membunuh saya bahwa itu tidak menggunakan daftar penginisialisasi untuk nama-nama. Paling tidak, Anda pasti berhasil memberikan kode yang hanya merasa rekayasa berlebihan. Saya tidak tahu apakah itu karena "kepatuhan" atau semua komentar bising: P
vmrob

6

JavaScript

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

Maaf, Math.randomtidak mengambil parameter, dan akan selalu mengembalikan angka dari [0, 1). Namun, itu adalah fungsi variadic yang menyenangkan dan tidak mengeluh tentang argumen!


5

Python

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 (acak) memberikan string konstan; bukan nilai acak


6
Catatan yang agak tidak relevan: jika Anda menggunakan Python 3.2 atau lebih baru, argumen kedua random.seed()adalah 2(default). Jika Anda lulus version=1, hash()string akan digunakan sebagai seed alih-alih seluruh string, dan karena Python secara acak seeded nilai hash string dimulai pada 3,2, Anda akan mendapatkan nama yang benar-benar acak.
Blacklight Shining

5

Perl

Sebaiknya Emma tidak melupakan dompetnya! Berjalan di bawah strictdan 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.

Penjelasan di sini .


Perl 5.18 mengubah ini sedikit, dengan memperkenalkan pengacakan kunci hash (untuk menghindari serangan kompleksitas tabrakan hash).
Konrad Borowski

4

JavaScript

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

The |0hasil 0 sepanjang waktu tapi terlihat seperti itu melakukan beberapa pembulatan lainnya.


Saya suka itu. Meskipun saya akan melakukan parseInt(Math.random(0, 4))dan mungkin menambahkan komentar seperti - Math.randommengembalikan ganda, jadi konversikan ke integer terlebih dahulu
Claudiu

5
Triknya sebenarnya Math.randomtidak mempedulikan parameter kita yang sedikit. Ia memilih angka dengan caranya sendiri. yang |0benar pembulatan hasil yang tak terduga, dan bukan sumber tipu daya apapun.
Tertarik

|0sangat jelas bagi sebagian orang (kita semua kemungkinan besar), tetapi saya berani bertaruh ada banyak yang tidak tahu apa fungsinya. Itulah kelompok yang saya andalkan untuk ditipu.
Matt

3
@ Matt Maksud saya |0, jika Anda tahu apa yang dilakukannya, sepertinya itu pembulatan ke bawah, dan itu adalah pembulatan ke bawah, sehingga tidak penipuan. (Dan jika seseorang tidak tahu apa yang |0dilakukan, maka tidak ada gunanya kode menipu; Anda bisa memberi tahu mereka apa pun yang Anda ingin mereka percayai.) Sebaliknya, perilaku tak terduga dalam jawaban Anda didasarkan pada fakta yang Math.random(0,4)secara fungsional identik dengan Math.random(), karena Math.randomtidak menggunakan parameter.
Tertarik

4

J

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

Kasihan Julie ... Trivia: ini mungkin J terbersih yang pernah saya tulis ...

Kode ini sebenarnya benar, kecuali untuk satu hal. ?.adalah rng seragam: ?.5akan selalu kembali 4. ?5sudah benar.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.