สคริปต์แบบสุ่มที่ไม่ได้สุ่มจริงๆ


106

ในฐานะที่เป็นเรื่องตลกเล็กน้อยในสำนักงานใครบางคนต้องการสคริปต์ที่สุ่มเลือกชื่อและคนที่กล่าวว่าจะทำให้รอบเครื่องดื่ม

มาเรียกผู้คนว่า John, Jeff, Emma, ​​Steve และ Julie

ฉันคิดว่ามันคงเป็นเรื่องตลกที่จะสร้างสคริปต์ที่ดูสุ่มได้อย่างรวดเร็ว แต่จริงๆแล้วให้คนเดียวกับผลลัพธ์ (ขึ้นอยู่กับคุณว่าคุณเลือก)

คำตอบที่โหวตมากที่สุดจะชนะหลังจากผ่านไปหนึ่งสัปดาห์

และผู้ชนะคือ....

Paul R ด้วย (ปัจจุบัน) 158 คะแนนโหวต

คำตอบที่นี่ดีมากและถ้าใครมีแนวคิดอื่นที่ยังไม่ได้โพสต์โปรดเพิ่มพวกเขาฉันรักการอ่านผ่านพวกเขา



6
@AstroCB หนึ่งในรายการโปรดของฉัน ด้านหลังโต๊ะบ๊อบบี้
Cruncher

50
ดูเหมือนว่ามันจะดูน่าหัวเราะถ้าเป็นการสุ่มยกเว้นว่าอย่าเลือกใครสักคน
เบรนแดน Long

6
@AstroCB อันนี้ก็ยอดเยี่ยม: dilbert.com/strips/comic/2001-10-25
gilbertohasnofb

3
ฉันผ่านหน้าแรก: คำตอบส่วนใหญ่มักเลือกจอห์นอันดับที่สองคือจูลี่เจฟฟ์ถูกเลือกน้อยมากและสตีฟโดย 1 แม้กระทั่งเรย์ก็ถูกเลือกโดยหนึ่ง แต่ไม่มีใครเลือกเอ็มมา คุณธรรมของเรื่องราว: เมื่อยืนอยู่ในแถวเพื่อตัดสินใจแบบสุ่มว่าใครจะซื้อเครื่องดื่มให้ตั้งชื่อตัวเองว่าเอ็มม่า
ตัวแปรที่น่า

คำตอบ:


171

C

สิ่งสำคัญคือต้องตัดสินใจว่าใครจะซื้อให้เร็วที่สุดเพื่อไม่ให้เสียเวลาดื่มอย่างมีค่า - ดังนั้นCจึงเป็นตัวเลือกที่ชัดเจนเพื่อให้ได้ประสิทธิภาพสูงสุด:

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

int main(void)
{
    const char *buyer;
    int n;

    srand(time(NULL)); // make sure we get a good random seed to make things fair !
    n = rand();
    switch (n % 5)
    {
        case 0: buyer = "John";
        case 1: buyer = "Jeff";
        case 2: buyer = "Emma";
        case 3: buyer = "Steve";
        case 4: buyer = "Julie";
    }
    printf("The person who is buying the drinks today is: %s !!!\n", buyer);
    return 0;
}

คำอธิบาย:

นี้จะทำงานได้ดีถ้ามีbreak;หลังจากแต่ละกรณีในงบสลับ อย่างไรก็ตามในแต่ละกรณี "ล้มเหลว" กับอีกคนหนึ่งจูลี่ที่ยากจนจึงมักจะซื้อเครื่องดื่มเสมอ


17
+1 สำหรับประสิทธิภาพ - เร็วกว่าการกลิ้งตัวตาย! ;)
Jwosty

16
ฉันกำลังคิดเกี่ยวกับการปรับให้เหมาะสมต่อไปบางทีด้วย SIMD หรือ GPGPU เพียงเพื่อเพิ่มประสิทธิภาพเล็กน้อย ;-)
Paul R

7
ใช้งานจริงได้จริง ไม่มีใครเคยถามด้วยซ้ำว่าเป็นอุบัติเหตุเพียงเล็กน้อย
iFreilicht

5
มันเป็นแค่ฉันหรืออันนี้ชัดเจนเกินไปที่จะเห็น?
Alvin Wong

3
@AlvinWong ฉันไม่ได้สังเกตเห็นมันทันที จากนั้นอีกครั้งฉันไม่ได้ใช้ C เป็นประจำหรือภาษาอื่น ๆ ที่สืบทอดมาจาก BCPL
Rhymoid

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 / สุ่มอย่างมีความสุขที่จะเห็นว่ามัน (อาจ) ไม่สามารถแยกมันและเกิดขึ้นกับจำนวนที่เหมาะสม 0 แทน ท้ายที่สุดแล้วการแจ้งให้โปรแกรมเมอร์ทราบถึงข้อผิดพลาดที่อาจเกิดขึ้นถือเป็นบาปร้ายแรงใน PHP


25
คุณต้องรัก PHP และยิ่งกว่านั้นบางครั้งมันก็จะไม่เลือกคนอื่น ดังนั้นหากคุณโชคดีมันจะดูเหมือนลำเอียงเล็กน้อยในตอนแรก
ฟัลโก

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เธรดจะไม่ทำงาน


24
นั่นคือความโหดร้าย!
Daenyth

8
รู้สึกเหมือนกำลังถ่ายรูปลูกเต๋าที่ยังไม่หยุดเคลื่อนไหว
วิ

1
@Vi นั่นเป็นการเปรียบเทียบที่ดี โชคดีที่การใช้ MVars รับประกันได้ว่าภาพจะไม่พร่ามัว :)
monocell

@monocell ในทางเทคนิคแล้วแม้แต่ภาพถ่ายของวัตถุที่เคลื่อนไหวก็สามารถล้างได้
ghosts_in_the_code

75

Bash - ความเรียบง่ายสูงสุด

ตัวอย่างที่ง่ายมาก - มาหลีกเลี่ยงปัญหาใด ๆ ด้วยวิธีทำแบบเรียน อย่าลืมที่จะเพาะกำเนิดจากนาฬิการะบบเพื่อให้ได้ผลลัพธ์ที่ดี!

#!/bin/bash

names=(John Jeff Emma Steve Julie)   # Create an array with the list of names
RANDOM=$SECONDS                      # Seed the random generator with seconds since epoch
number=$((RANDOM % 5))               # Pick a number from 0 to 4
echo ${names[number]}                # Pick a name

สิ่งนี้ขึ้นอยู่กับผู้ใช้ที่ไม่ทราบว่า$SECONDSbuiltin ทำอะไร มันจะคืนค่าจำนวนวินาทีนับตั้งแต่เชลล์ปัจจุบันเริ่มต้นขึ้น เมื่อมันอยู่ในสคริปต์เชลล์จะเริ่มต้นที่ศูนย์เมื่อวินาทีที่แล้วดังนั้นเครื่องกำเนิดมักจะมีเมล็ดอยู่เสมอ0และจูลี่ก็ซื้อเบียร์เสมอ

โบนัส:

อันนี้ยืนขึ้นเพื่อตรวจสอบข้อเท็จจริงค่อนข้างดี; หากคุณป้อนรหัสเดียวกันใน commandline แทนที่จะเป็นสคริปต์สคริปต์จะให้ผลลัพธ์แบบสุ่มเนื่องจาก$SECONDSจะส่งคืนระยะเวลาที่เชลล์เชิงโต้ตอบของผู้ใช้ทำงาน


9
\ o / ค่าเฉลี่ย !!! หมายถึงจริงๆ !!! $SECONDSFTW! \ o /
yeti

จะเกิดอะไรขึ้นถ้าคุณทำsourceเช่นนี้แทนที่จะทำมัน? Shebang จะยังคงเรียกกระสุนใหม่หรืออะไรบางอย่างหรือไม่
jpmc26

1
@ jpmc26: ถ้าคุณรันด้วยsourceมันจะเหมือนกับว่าคุณพิมพ์คำสั่งบน commandline ด้วยตัวเอง; #! / bin / bash เป็นความคิดเห็นดังนั้นจึงไม่สนใจ นี่เป็นความจริงของสคริปต์ใด ๆ
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]);
        }
    }
}

สิ่งนี้อาจไม่หลอกผู้ที่คุ้นเคยกับ. 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 เสมอเนื่องจากค่าสูงสุดนั้นไม่รวมกัน


42

Q

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

Q เริ่มต้นเสมอเมล็ดจำนวนสุ่มด้วยค่าเดียวกัน


8
ดังนั้นโดยทั่วไปจะไม่สุ่มเลย
Sam Creamer

3
@ SamCreamer วัตถุประสงค์ของคำถามเป็นอย่างมากที่จะทำให้การส่งออกที่ไม่สุ่ม แต่นี่ดูสุ่มดังนั้นมันจึงเหมาะกับใบเสร็จอย่างแน่นอน
Cruncher

4
ขออภัยฉันหมายถึงตัวเลขสุ่มของ Q ไม่ใช่แบบสุ่มคำถามนี้ตรงตามเกณฑ์อย่างแน่นอน ไม่ได้หมายความว่าจะเจอแบบนั้น!
Sam Creamer

ใช่คุณต้องหาวิธีของคุณในการสร้างเมล็ดสุ่มทุกครั้งที่คุณต้องการใช้แรนด์? เสียง ... มีประโยชน์
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";

Prints: 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]คือ hash slice ใน Perl ดังนั้น@indexจะถูกประเมินในบริบทรายการ ในกรณีนี้มันเป็นรายการเดียวและนั่นเป็นสาเหตุที่ทำให้ทำงานได้อย่างถูกต้อง


ดังนั้นในเงื่อนไข C (++) มีการแปลงโดยนัยจากรายการเป็นสเกลาร์เกิดขึ้นเพราะเมื่อมีการจัดทำดัชนีคาดว่าสเกลาร์จะทำอย่างไร
iFreilicht

@iFreilicht ถูกต้อง ใน Perl คุณสามารถประเมินนิพจน์เป็นรายการหรือเป็นเซนต์คิตส์และเนวิสขึ้นอยู่กับว่าพวกเขาปรากฏที่ไหน ดังนั้นการแสดงออกเดียวกันอาจหมายถึงสิ่งที่แตกต่างกันขึ้นอยู่กับบริบท รายการตัวแปร (เช่นตัวแปรที่มี@คำนำหน้า) ใน "บริบทรายการ" ถูกตีความว่าเป็นองค์ประกอบทั้งหมด แต่ใน "บริบทสเกลาร์" เป็นสเกลาร์เท่ากับจำนวนองค์ประกอบทั้งหมดในรายการ Person X is buyingดังนั้นภายในสตริงตัวแปรรายการมีบริบทรายการและได้รับหยันและเราได้รับ แต่ในฐานะที่เป็นดัชนีอาเรย์จะได้รับบริบทสเกลาร์และได้รับการตีความว่าเป็น 1
Allen G

3
ปัญหานี้คือเมื่อโปรแกรมเมอร์ Perl เห็นmy @index = ...เขาสงสัยทันที "WTF ?!"
Derobert

@derobert ทำไมคุณถึงสงสัย? คุณเห็นรหัสเช่นนั้นค่อนข้างบ่อย ... my @letters = 'a' .. 'z'; my @squares = map $_**2, 1..20; my @sorted = sort { lc $a cmp lc $b } @words;ฯลฯ
Matthias

@ Matias เนื่องจากบรรทัดคือการเลือกและเก็บค่าเดียวและแทนที่จะเป็นเซนต์คิตส์และเนวิสมันถูกเก็บไว้ในอาร์เรย์
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]);

มันมักจะหยิบจูลี่

มันมีวงเล็บอยู่ภายในวงเล็บเหลี่ยมและผู้ประกอบการเครื่องหมายจุลภาคส่งกลับค่าของตัวถูกดำเนินการด้านขวา
นอกจากนี้ยังง่ายมากที่จะพลาด ฉันเคยพลาดมาก่อนในรหัสจริง


มันช่างน่ายินดี ในที่สุดการใช้งานสำหรับผู้ประกอบการที่น่ากลัวและน่ากลัว
Keen

5
เครื่องหมายจุลภาคในบริบทนั้นเป็นตัวดำเนินการทางเทคนิคแทนที่จะเป็นตัวคั่น ecma-international.org/ecma-262/5.1/#sec-11.14และมันแย่มาก ถ้าคุณไม่ต้องการให้โค้ดอ่านยาก ในขณะที่คุณทำที่นี่ ดังนั้นความรุ่งโรจน์
Keen

2
@Cory ใช่ฉันเห็นด้วย - แม้ว่าฉันจะใช้มันตลอดเวลาสำหรับ Code Golf ด้วยฟังก์ชั่นการแสดงออก (เช่น(a,b)=>(a=b[0],b)) ฉันชี้แจงคำตอบของฉันชัดเจน
แปรงสีฟัน

21

C #

using System;

namespace LetsTroll {
    class Program {
        static void Main() {
            var names = new string[]{ "John", "Jeff", "Emma", "Steve", "Julie" };
            var random = new Random(5).NextDouble();
            var id = (int)Math.Floor(random);
            Console.WriteLine(names[id]);
        }
    }
}

เคล็ดลับคือเมธอดnew Random().NextDouble()ส่งคืนค่าเป็นสองเท่าระหว่าง 0 ถึง 1 โดยการใช้Math.Floor()กับค่านี้มันจะเป็น 0 เสมอ


24
มันไม่ทนต่อการมองแวบเดียวของฉัน ;)
Martin Ender

1
@TimS เช่นนั้น? : P
Knerd

2
+1, ดีกว่ามาก - ฉันรู้ว่าคุณกำลังทำอะไรอยู่ แต่มันอาจหลอกคนที่ไม่คุ้นเคยกับ API
Tim S.

1
ฉันไม่รู้เกี่ยวกับสิ่งนี้ หากคุณกำลังจะระบุเมล็ดพันธุ์ทำไมไม่ใช้วิธีที่เหมาะสมในการรับ "สุ่ม" int:var random = new Random(5); var id = random.NextInt(5);
clcto

2
@clcto ในความคิดของฉันรวมถึงสองครั้งมีแนวโน้มที่จะทำให้คนทำสองครั้งถามว่าทำไมและดูปัญหา รวมไว้เพียงครั้งเดียวแล้วรวมถึงรหัสที่ไม่จำเป็นในภายหลังให้การเปลี่ยนเส้นทาง / การใช้เล่ห์เหลี่ยมเล็กน้อย โบนัส: ถ้ามีคนแก้ไขข้อบกพร่องข้อหนึ่งข้อหนึ่งก็มีอยู่
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]);

คำแนะนำ:

สร้างเมล็ดพันธุ์จาก GUID Guids มีโอกาสชน 4 × 10−10 สุ่มสุด ๆ

ตอบ:

อย่างน้อยเมื่อคุณใช้Guid.NewGuid()อ๊ะ! (วิธีที่จะทำให้เป็นเมล็ดเสมอ 0) ยังไม่มีจุดหมาย (int) สำหรับการชี้ทิศทางผิด


วิธีอื่น ๆ ผมอาจจะทำมันคือการได้รับAddRangeงงกับเมื่อมีการเพิ่มชื่อให้เป็นConcat List<string>เกิดขึ้นกับฉันที่จะมี Hashset ที่มี IEqualityComparer ที่ลับๆล่อๆ แต่มันคงแปลกเกินไป เครดิตของฉันมีไม่มาก (ถ้ามี) คำตอบจากเมล็ดเมื่อฉันโพสต์นี้
Nathan Cooper

ฉันจะเดาว่าคุณมีความคิดเช่นเดียวกับฉัน แต่คุณเร็วขึ้นเล็กน้อยและทำให้ยากขึ้นที่จะเห็น +1!
tsavinho

7
การสร้างตัวสร้างตัวเลขสุ่มเป็นการหลอกลวงที่ชัดเจน แต่คุณซ่อนมันไว้ที่นี่อย่างยอดเยี่ยม การทำงานที่น่ารัก
TRiG

18

ทุบตี / coreutils

สิ่งนี้ใช้เวลาเกือบทุกคำจากสคริปต์ที่ฉันเขียนเพื่อจุดประสงค์ที่คล้ายกัน

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

แม้แต่การลืมใช้ตัวพิมพ์ใหญ่ R เป็นความผิดพลาดที่ฉันได้ทำในชีวิตจริงของสคริปต์


3
คุณจะให้คำอธิบายที่ดีกว่านี้ได้ไหม? คนปัจจุบันของคุณสั้นจริงๆและไม่เป็นประโยชน์กับคนที่ไม่คุ้นเคยกับการทุบตี
iFreilicht

6
-rระบุการเรียงลำดับย้อนกลับ (lexicographic) ดังนั้น Steve จะถูกเลือกเสมอ มันอาจถูกมองว่าเป็นตัวพิมพ์ที่ไร้เดียงสา-Rสำหรับการเรียงลำดับแบบสุ่ม
สูงสุด

3
นั่นเป็นการเตือนที่ดีว่าอย่าเชื่อใจความคิดเห็น แต่เพื่ออ่านรหัสอย่างละเอียด!
TecBrat

16

ทับทิม

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

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

สิ่งนี้จะทำงานได้อย่างถูกต้องsort_byแต่sortคาดว่าจะมีฟังก์ชั่นการเปรียบเทียบที่ใช้งาน<=>ได้ ผลลัพธ์ของ rand () จะเป็นค่าบวกเสมอดังนั้นมันจะให้ผลลัพธ์ที่เท่าเทียมกันเสมอหากsortอัลกอริทึมของการใช้ทับทิมของคุณนั้นถูกกำหนดไว้แล้ว Ruby 1.9.3 ของฉันส่งผลให้ Julie เสมอ


12

ทับทิม

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

puts names[rand() % 5]

rand() โดยไม่มีการโต้แย้งสร้างสุ่มลอยระหว่าง 0 และ 1 ดังนั้น modulo 5 ไม่ทำอะไรเลยและเมื่อหั่นเป็นอาร์เรย์ที่มีอาร์กิวเมนต์ลอยทับทิมเพียงแค่ปัดลงมันจึงส่งกลับจอห์นเสมอ


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

คำอธิบาย

ไม่มี $ RANDOM ใน perl เป็นตัวแปรที่ไม่ได้กำหนด รหัสจะส่งคืนองค์ประกอบแรกจากรายการเสมอ - ดื่มกับ John :)

แก้ไข:

หลังจากผ่านรหัสหนึ่งในห้าคนได้ตัดสินใจที่จะแก้ไขข้อผิดพลาดที่เห็นได้ชัดผลิตโปรแกรมต่อไปนี้:

#!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จะส่งคืนดัชนีขององค์ประกอบสุดท้าย ตั้งแต่อาร์เรย์จะ zero-based ได้รับการอ้างอิงไปยังอาร์เรย์กับห้าองค์ประกอบที่จะ$#$aref_people ส่งกลับตัวเลขสุ่มที่มากกว่าหรือเท่ากับศูนย์และน้อยกว่าพารามิเตอร์ดังนั้นมันจะไม่กลับมาซึ่งหมายความว่า Julie จะไม่ซื้อเครื่องดื่มอย่างมีประสิทธิภาพ :)4
rand4


1
$RANDOMเป็นคุณลักษณะจริงใน bash, ksh และ zsh (แต่ไม่ใช่ใน perl)
kernigh

10

หลาม

ทุกคนรู้ว่าคุณไม่สามารถเชื่อถือแบบแผนในพื้นที่ตัวอย่างขนาดเล็กได้ เพื่อให้เป็นการสุ่มอย่างแท้จริงฉันได้ละทิ้งวิธีล้าสมัยในการเลือกชื่อจากรายการและโปรแกรมของฉันจะสะกดชื่อแบบสุ่มแทน เนื่องจากชื่อส่วนใหญ่ในสำนักงานมีตัวอักษร 4 ตัวเราจะจัดการเรื่องนั้น

import random

def CHR (n):
    # Just easily convert a number between 0 and 25 into a corresponding letter
    return chr(n+ord('A'))

# Seed the RNG with a large prime number. And multiply it by 2 for good measure.
random.seed (86117*2)

# Now, let's see what COMPLETELY RANDOM name will be spelled out!
totallyRandomName = ''
for i in range(4) :
    totallyRandomName += CHR(int(random.random()*26))

print (totallyRandomName)

โดยธรรมชาติฉันได้เตรียมงานบางอย่างเพื่อให้แน่ใจว่าฉันเลือกเมล็ดที่เหมาะสม


15
การสร้างตัวเลขสุ่มด้วยค่าคงที่นั้นชัดเจนเกินไป ..
Brendan Long

@BrendanLong มันจะยกคิ้วขึ้นแน่นอน ผู้คนต้องการทดสอบเพื่อให้แน่ใจว่าเป็นแบบสุ่ม และเมื่อมันไม่เดาว่าใครกำลังซื้อเครื่องดื่ม
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] );
}

ขออภัย Jeff!

หลังจากทำซ้ำไม่กี่ r == 1 mod 5 เพราะคณิตศาสตร์ คุณธรรม: อย่าเขียน PRNG ของคุณเองถ้าคุณทำคณิตศาสตร์ไม่ดี :)


10

c ++ x11

#include <vector>
#include <iostream>

int main () {
  std::srand(time(NULL));
  std::vector<std::string> choice{("jen","moss","roy")};
  std::cout << choice[rand()%choice.size()] << std::endl;
}

ขนาดของเวกเตอร์เป็นจริง 1 เนื่องจากวงเล็บที่ใช้ในรายการ initializer ผู้ประกอบการเครื่องหมายจุลภาคจะยกเลิกชื่อทั้งหมดและส่งคืนล่าสุดดังนั้นผู้ซื้อจะเป็นรอยเสมอ


10

สกาล่า

ฉันรู้ว่าผู้ใช้ของฉันจะสงสัยดังนั้นฉันจึงได้รวมหลักฐานว่าการสุ่มของฉันมีความยุติธรรมอย่างแท้จริง!

object DrinkChooser {

  def main(args: Array[String]): Unit = {
    proveRandomness()
    val names = List("John","Jeff","Emma","Steve","Julie")
    val buyer = names(randomChoice(names.size))
    println(s"$buyer will buy the drinks this time!")
  }

  def proveRandomness(): Unit = {
    val trials = 10000
    val n = 4
    val choices = for (_ <- 1 to 10000) yield randomChoice(n)
    (choices groupBy(identity)).toList.sortBy(_._1) foreach { case (a, x) =>
      println(a + " chosen " + (x.size * 100.0 / trials) + "%")
    }
  }

  def randomChoice(n: Int): Int = {
    var x = 1
    for (i <- 1 to 1000) { // don't trust random, add in more randomness!
      x = (x * randomInt(1, n)) % (n + 1)
    }
    x
  }

  // random int between min and max inclusive
  def randomInt(min: Int, max: Int) = {
    new scala.util.Random().nextInt(max - min + 1) + min
  }

}

ตัวอย่างการเรียกใช้:

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

จอห์นจะซื้อเครื่องดื่มทุกครั้งเว้นเสียแต่ว่าคนอื่นจะโชคดีอย่างยิ่ง

"การพิสูจน์" ของการสุ่มขึ้นอยู่กับความจริงที่ว่าrand(1, 4) * rand(1, 4) % 5ยังคงมีการกระจายอย่างเท่าเทียมกันระหว่าง 1 และ 4 รวม แต่rand(1, 5) * rand(1, 5) % 6จะเสื่อมสภาพ มีความเป็นไปได้ที่คุณจะได้รับ 0 ซึ่งจะทำให้ผลลัพธ์สุดท้ายเป็น 0 โดยไม่คำนึงถึง "สุ่ม" ที่เหลือ


10

Javascript (พร้อมUnderscore.js )

เนื่องจาก javascript ไม่มี 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) สิ่งนี้สามารถดำเนินการได้ดียิ่งขึ้นโดยใช้ตัวอักษรพิเศษหรือแบบอักษร


นี่ไม่ใช่จุดที่ยากที่สุด ทุกคนที่ได้สร้างNฟังก์ชั่น --ary ใน JavaScript รู้เกี่ยวกับargumentsตัวแปร
Conor O'Brien

8

C ++

เพื่อความเป็นธรรมเราควรทำการทดลองมากมายและเลือกผู้ที่ถูกเลือกบ่อยที่สุด

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

static const char *names[] = { "John", "Jeff", "Emma", "Steve", "Julie" };

int main() {
    srand(time(NULL));
    std::map<int, int> counts;

    // run 2^31 trials to ensure we eliminate any biases in rand()
    for (int i = 0; i < (1<<31); i++) {
        counts[rand() % (sizeof(names)/sizeof(*names))]++;
    }

    // pick the winner by whomever has the most random votes
    int winner = 0;
    for (std::map<int, int>::const_iterator iter = counts.begin(); iter != counts.end(); ++iter) {
        if (iter->second > counts[winner]) {
            winner = iter->first;
        }
    }

    printf("%s\n", names[winner % (sizeof(names)/sizeof(*names))]);
}

มูลค่าของ1<<31อะไร ขออภัยจอห์น


คำตอบสำหรับคำถามสปอยเลอร์ของคุณคือ UB ฉันไม่แน่ใจว่าสิ่งที่ทำให้ดีขึ้นหรือแย่ลง
nwp

@nwp แน่นอน แต่มันถือได้ทุกที่ int เป็นส่วนประกอบของ 32- บิต 2 ซึ่งดูเหมือนว่าจะเป็นเช่นนั้นแม้ใน 64- บิต (กับ gcc) ฉันยังไม่ได้ทดสอบกับเสียงดังกราว
ปุย

ไม่ไม่มีที่ใดก็ได้ที่ int เป็นส่วนประกอบ 32- แต่ 2 ค่า 1 << 31 ไม่ได้ถูกกำหนด คุณโชคดีที่พฤติกรรมที่ไม่ได้กำหนดทำให้คอมไพเลอร์เลือกสิ่งที่มันรู้สึกและเนื่องจากมันถูกสร้างขึ้นมาเพื่อความรวดเร็วจึงตัดสินใจที่จะไม่ทำอะไรเลยซึ่งเกิดขึ้นกับสิ่งที่คุณต้องการ
nwp

@nwp 1<<31 == 0x80000000ไม่ว่าโดยความหมายมาก<<และ 32 บิต 2 INT_MINส่วนประกอบที่ คุณอาจจะคิดว่า1<<32อาจจะ== 0ใช่หรือไม่? (เพราะเมื่อวันที่ x86 1<<32มักจะประเมินถึง 1 ... )
ปุย

@nwp จริงๆแล้วมันมีการกำหนดการใช้งาน ตอนนี้ถ้าเรามีการพูดคุยเกี่ยวกับ C, แล้วมันจะไม่ได้กำหนด
Stuart Olsen

7

T-SQL (2008+)

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

คำอธิบาย:

ใน MS SQL Server RAND()ประเมินเพียงหนึ่งครั้งต่อการดำเนินการ ทุกชื่อจะได้รับหมายเลขเดิมเสมอโดยคงลำดับเดิมไว้ จอห์นเป็นคนแรก ห่วยจอห์น

การปรับปรุงที่แนะนำ:

T-SQL RAND(CHECKSUM(NEWID()))สามารถผลิตที่มีคุณภาพที่ดีต่อแถวกับตัวเลขสุ่ม


ฉันคิดว่าการสั่งซื้อโดย NEWID () จะพอเพียง (ไม่จำเป็นต้องเช็ค)
Jacob

7

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.randomseedRNG ที่ดี น่าเศร้าที่จูลี่ซื้ออยู่เสมอ (อย่างน้อยในคอมพิวเตอร์ของฉัน)


math.random()มีข้อโต้แย้งใด ๆ [0,1)นอกจากนี้ยังมีผลตอบแทนที่ตัวเลขในช่วง -1 สำหรับการไม่จับที่
mniip

@mniip: สมควรได้รับอย่างแท้จริงเช่นกัน! ฉันซ่อมมันแล้ว
Kyle Kanos

6

สำนวน C ++ 11

เมื่อมีส่วนร่วมกับเครื่องดื่มเป็นสิ่งสำคัญโดยเฉพาะอย่างยิ่งที่จะทันสมัยกับมาตรฐานล่าสุดและรูปแบบการเข้ารหัส; นี่เป็นตัวอย่างที่ยอดเยี่ยมของตัวเลือกชื่อ C ++ 11 ที่มีประสิทธิภาพและสอดคล้องกับสำนวน

มันเป็นเมล็ดจากนาฬิกาของระบบและส่งออกเมล็ดพร้อมกับชื่อสำหรับการตรวจสอบในแต่ละครั้ง

#include <vector>
#include <chrono>
#include <random>
#include <iostream>

auto main()->int {
  std::vector<std::string> names;           // storage for the names
  names.reserve(5);                         // always reserve ahead, for top performance
  names.emplace_back("John");               // emplace instead of push to avoid copies
  names.emplace_back("Jeff");
  names.emplace_back("Emma");
  names.emplace_back("Steve");
  names.emplace_back("Julie");

  std::mt19937_64 engine;                   // make sure we use a high quality RNG engine
  auto seed((engine, std::chrono::system_clock::now().time_since_epoch().count()));  // seed from clock
  std::uniform_int_distribution<unsigned> dist(0, names.size() - 1);     // distribute linearly
  auto number(dist(engine));                // pick a number corresponding to a name
  std::string name(names.at(number));       // look up the name by number
  std::cout << "Seed: " << seed << ", name: " << name << std::endl;  // output the name & seed
  return EXIT_SUCCESS;                      // don't forget to exit politely
}

ลองถ่ายทอดสด: http://ideone.com/KOet5H

ตกลงดังนั้นนี่เป็นรหัสที่ดีโดยรวม มีปลาเฮอริ่งแดงจำนวนมากที่จะทำให้คุณมองอย่างใกล้ชิดเกินกว่าที่รหัสจะสังเกตเห็นได้ชัดเจน - RNG นั้นไม่เคยมีการเพาะจริง :) ในกรณีนี้seedเป็นเพียงจำนวนเต็มและในขณะที่มันดูเหมือนengineจะถูกส่งเป็นพารามิเตอร์ให้กับ ฟังก์ชั่นการเพาะมันไม่สนใจเลย ตัวแปรเมล็ดถูกตั้งค่าจากนาฬิกาดังนั้นมันสามารถส่งออกได้ในตอนท้ายพร้อมกับชื่อเพื่อเพิ่มการดูถูกการบาดเจ็บ แต่มันจะยังคงเป็นสตีฟที่ซื้อเครื่องดื่มอยู่เสมอ


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) ให้สตริงคงที่ ไม่ใช่ค่าสุ่ม


6
บันทึกย่อที่ไม่เกี่ยวข้อง: หากคุณใช้ Python 3.2 หรือใหม่กว่าอาร์กิวเมนต์ที่สองที่random.seed()ต้องเป็น2(ค่าเริ่มต้น) หากคุณผ่านversion=1การใช้งานhash()ของสตริงจะใช้เป็นเมล็ดแทนสตริงทั้งหมดและเนื่องจาก Python จะสุ่มค่าแฮชของสตริงเริ่มต้นใน 3.2 คุณจะได้รับชื่อสุ่มจริง
Blacklight Shining

5

Perl

เอ็มม่าดีกว่าอย่าลืมกระเป๋าเงินของเธอ! ทำงานภายใต้และstrictwarnings

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 เปลี่ยนสิ่งนี้เล็กน้อยโดยแนะนำการสุ่มคีย์แฮช (เพื่อหลีกเลี่ยงการโจมตีที่ซับซ้อนของการชนกันของแฮช)
Konrad Borowski

4

JavaScript

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

|0ผลใน 0 ตลอดเวลา แต่ดูเหมือนว่ามันทำบางปัดเศษอื่น ๆ


ฉันชอบมัน. แม้ว่าฉันจะทำparseInt(Math.random(0, 4))และอาจเพิ่มความคิดเห็นเช่น - Math.randomคืนค่าสองเท่าดังนั้นแปลงเป็นจำนวนเต็มก่อน
Claudiu

5
เคล็ดลับคือจริง ๆ แล้วMath.randomไม่สนใจสิ่งใดสำหรับพารามิเตอร์น้อย มันเลือกตัวเลขในแบบของตัวเอง |0อย่างถูกต้องปัดเศษผลที่ไม่คาดคิดและไม่ได้เป็นแหล่งที่มาของการใช้กลอุบายใด ๆ
Keen

|0ชัดเจนมากสำหรับบางคน (เราทุกคนเป็นไปได้มากที่สุด) แต่ฉันพนันได้เลยว่ามีหลายคนที่ไม่รู้ว่ามันทำอะไร นั่นคือกลุ่มที่ฉันพึ่งหลอก
Matt

3
@ แมทฉันหมายถึงว่า|0ถ้าคุณรู้ว่ามันทำอะไรดูเหมือนว่ามันจะถูกปัดเศษลงและมันจะปัดเศษลงดังนั้นจึงไม่ใช่เรื่องหลอกลวง (และถ้ามีคนที่มีความคิดในสิ่งที่ไม่มี|0ไม่แล้วมีการใช้รหัสหลอกลวงไม่มี. คุณก็สามารถบอกพวกเขาสิ่งที่คุณต้องการให้พวกเขาเชื่อว่า) แต่พฤติกรรมที่ไม่คาดคิดในคำตอบของคุณจะขึ้นอยู่กับความจริงที่ว่าMath.random(0,4)เป็นหน้าที่เหมือนกับMath.random(), เพราะMath.randomไม่ได้ใช้พารามิเตอร์
Keen

4

J

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

แย่ Julie ... เรื่องไม่สำคัญ: นี่อาจเป็น J ที่สะอาดที่สุดที่ฉันเคยเขียน ...

รหัสนี้ถูกต้องจริงยกเว้นสิ่งหนึ่ง ?.rng สม่ำเสมอคือ: ?.5จะกลับ 4. ?5จะถูกต้องเสมอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.