เลือกตัวเลขสุ่มระหว่าง 0 ถึง n โดยใช้แหล่งที่มาของการสุ่ม


26

งาน

กำหนดให้เป็นจำนวนเต็มบวกnน้อยกว่าที่2^30ระบุไว้เป็นอินพุตในวิธีที่คุณเลือกรหัสของคุณควรส่งออกจำนวนเต็มแบบสุ่มระหว่าง0และnรวม หมายเลขที่คุณสร้างควรจะเลือกอย่างสม่ำเสมอโดยการสุ่ม นั่นคือแต่ละค่าจาก0ถึงnต้องเกิดขึ้นกับความน่าจะเป็นที่เท่ากัน (ดูกฎและคำเตือน)

กฎและคำเตือน

รหัสของคุณสามารถสันนิษฐานได้ว่าตัวสร้างตัวเลขสุ่มใด ๆ ที่สร้างขึ้นในภาษาหรือไลบรารีมาตรฐานของคุณที่อ้างว่าสุ่มอย่างสม่ำเสมอนั้นเป็นชุดเครื่องแบบ นั่นคือคุณไม่ต้องกังวลเกี่ยวกับคุณภาพของแหล่งข้อมูลแบบสุ่มที่คุณใช้ อย่างไรก็ตาม

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

หมายเหตุ

  • randInt(0,n) ไม่ถูกต้องเนื่องจากรับอินพุตเป็นอาร์กิวเมนต์สำหรับฟังก์ชัน builtin หรือ library
  • rand()%nจะไม่ให้หมายเลขสุ่มที่เหมือนกันโดยทั่วไป เป็นตัวอย่างที่กำหนดโดย betseg ถ้าintmax == 15และn = 10แล้วคุณจะมีโอกาสมากขึ้นที่จะได้รับมากกว่า0-56-10
  • floor(randomfloat()*(n+1)) จะไม่ให้ตัวเลขสุ่มแบบทั่วไปโดยทั่วไปเนื่องจากจำนวน จำกัด ของค่าจุดลอยตัวที่เป็นไปได้ที่แตกต่างกันระหว่าง 0 ถึง 1

คุณจะยืนยันได้อย่างไรว่าผลลัพธ์นั้นเป็นแบบสุ่มอย่างสม่ำเสมอ อาจเป็นได้ว่าภาษา / ไลบรารีที่กำหนดจะแสดงผลตัวเลขสุ่มอย่างสม่ำเสมอ แต่การจัดการอาจส่งผลให้เกิดผลลัพธ์ที่ไม่สม่ำเสมอ (เช่นrng()ให้0- 100ถ้าn = 75และฟังก์ชั่นคือrng()%75แล้ว 0-25 จะเป็นเรื่องธรรมดามากขึ้น ... )
Baldrickk

1
@Baldrickk ด้วยภูมิปัญญาของฝูงชน :) เราสามารถอ่านโค้ดและคิดดูได้เท่านั้น

บทสรุปที่น่าเศร้าของการถามคำถามทฤษฎีความน่าจะเป็นที่เป็นไปได้ที่ง่ายที่สุด: การสุ่มและความน่าจะเป็นเข้าใจได้ไม่ดีมาก :( (และกฎการอ่านยากมาก)
Martin Ender

สิ่งนี้อยู่ในใจ: หมายเลขสุ่ม
BgrWorker

ทำไมคุณถึงยอมรับคำตอบ x86 เมื่อมีคำตอบสั้น ๆ สามข้อ
Dennis

คำตอบ:


25

x86 เครื่องจักรด้วย rdrandคำสั่ง 10 ไบต์

BITS 64

_try_again:

 rdrand eax
jnc _try_again

 cmp eax, edi
ja _try_again

 ret

รหัสเครื่อง

0FC7F0 73FB 39F8 77F7 C3

การป้อนข้อมูลที่อยู่ในการลงทะเบียนและการส่งออกในrdi สิ่งนี้เป็นไปตามSYS V AMD64 ABIดังนั้นโค้ดจึงใช้งานฟังก์ชัน C ได้อย่างมีประสิทธิภาพrax

unsigned int foo(unsigned int max); 

ด้วย ints 32 บิต

คำสั่งrdrandนั้นอธิบายโดย Intel

RDRANDส่งคืนตัวเลขสุ่มที่จัดหาโดยตัวสร้างบิตแบบสุ่มที่มีความปลอดภัยและเข้ารหัสแบบกำหนดค่าได้ DRBG DRBG ถูกออกแบบมาเพื่อตอบสนองความNIST SP 800-90Aมาตรฐาน

การจัดการกับ CSRNG นั้นเป็นการบอกเป็นนัยว่าการแจกแจงมีความเหมือนกันโดยอ้างข้อความ NIST SP 800-90A:

หมายเลขสุ่มคืออินสแตนซ์ของตัวแปรสุ่มที่ไม่เอนเอียงคือผลผลิตที่ผลิตโดยกระบวนการสุ่มที่กระจายแบบสม่ำเสมอ


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

เนื่องจากeaxเป็น 32 บิตrdrandส่งคืนตัวเลขระหว่าง 0 ถึง 2 32 -1 ดังนั้นสำหรับทุก ๆnใน [0, 2 32 -1] จำนวนการทำซ้ำที่คาดหวังคือ 2 32 / (n + 1) ซึ่งกำหนดไว้สำหรับnทั้งหมดใน [0, 2 30 )


ระดับต่ำอย่างยอดเยี่ยม ขอขอบคุณ.

อะไรjncหา?
l4m2

@ l4m2 rdrandตั้งค่าCFถ้าข้อมูลที่ส่งคืนนั้นถูกต้อง ข้อมูลอาจไม่ถูกต้องเนื่องจากมีคำขอมากเกินไปที่จะระบายเอนโทรปี ดูรายการคู่มือสำหรับrdrandและนี้
Margaret Bloom

20

เยลลี่ , 7 6 ไบต์

⁴!!X%‘

ขอบคุณ @JonathanAllan สำหรับการตีกอล์ฟ 1 ไบต์!

ไม่สามารถรันบน TIO ได้เพราะ(16!)! เป็นขนาดใหญ่จำนวน

มันทำงานอย่างไร

⁴!!X%‘  Main link. Argument: n

⁴       Set the return value to 16.
 !!     Compute (16!)!.
   X    Pseudo-randomly choose an integer between 1 and (16!)!.
        Since (16!)! is evenly divisible by any k ≤ 2**30, it is evenly divisible
        by n+1.
    %‘  Take the result modulo n+1.

นี่เป็นคำตอบที่ลบแล้วของฉันซึ่งเป็นแนวคิดเดียวกัน แม้ว่าฉันจะมีการยกกำลังที่ไม่จำเป็น
orlp

ขออภัยฉันไม่ได้ดูก่อนโพสต์
เดนนิส

โอ้ไม่เป็นไรฉันไม่ได้วางแผนที่จะซ่อมมันอยู่ดี ฉันรู้สึกอึดอัดกับ Jelly ที่จะเล่นกับมันจริงๆ
orlp

1
"เซอร์ฉันไม่รู้ว่าทำไมคุณถึงบ้าคลั่งอัลกอริธึมเป็นเวลาคงที่นั่นเป็นสิ่งที่ดีใช่มั้ยทำไมความปลอดภัยและทรัพยากรบุคคลนอกประตู"
corsiKa

1
ตกลง ความแตกต่างเล็กน้อยระหว่างตัวเลข 8 ตัวและตัวเลข 417 ล้านล้านหลัก: p
Jonathan Allan

11

Mathematica, 29 ไบต์

ขึ้นอยู่กับเดนนิสคำตอบของวุ้น

RandomInteger[2*^9!-1]~Mod~#&

ฉันจะไม่แนะนำให้ใช้สิ่งนี้จริง ๆ 2e9!เป็นจำนวนมาก ...

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

การสุ่มตัวอย่างการปฏิเสธ 34 ไบต์

วิธีเก่าของฉันที่นำไปสู่รหัสที่ค่อนข้างน่าสนใจมากขึ้น:

13!//.x_/;x>#:>RandomInteger[13!]&

การสุ่มตัวอย่างการปฏิเสธพื้นฐาน เราเริ่มต้นผลลัพธ์ที่13! (ซึ่งมีขนาดใหญ่กว่าอินพุตสูงสุด2 30 ) จากนั้นแทนที่มันซ้ำ ๆ ด้วยจำนวนเต็มแบบสุ่มระหว่าง0ถึง13! ตราบใดที่ค่ามีค่ามากกว่าอินพุต


1
คุณหมายถึง "เล็กกว่าหรือเท่ากับอินพุต" หรือไม่?

1
@ หมายเลข Lembik เราต้องการสร้างค่าใหม่ตราบใดที่ไม่ตกอยู่ในช่วงที่ต้องการ
Martin Ender

อ้อเข้าใจแล้ว. ด้วยเหตุผลบางอย่างฉันคิดว่าเราสุ่มตัวอย่างจากช่วงที่ต้องการซ้ำ ๆ ขอบคุณ

1
เตือนฉันให้เพิ่มเวลา จำกัด ในครั้งต่อไป :)

9

Brachylogขนาด 9 ไบต์

≥.∧13ḟṙ|↰

ลองออนไลน์!

วิธีนี้ใช้13!ในคำตอบของ Martin Ender ( 13ḟน้อยกว่าหนึ่งไบต์2^₃₀)

มีการใช้random_between/3งานซึ่งเมื่อขุดแหล่งที่มาการใช้งานrandom_float/0ที่เชื่อมโยงกับrandom/1ที่ใช้อัลกอริทึม Mersenne Twister ซึ่งเป็นชุดสำหรับวัตถุประสงค์ของเรา

คำอธิบาย

≥.           Input ≥ Output
  ∧          And
   13ḟṙ      Output = rand(0, 13!)
       |     Else
        ↰    Call recursively with the same input

7

Prolog (SWI) , 38 ไบต์

X*Y:-Z is 2^31,random(0,Z,Y),Y=<X;X*Y.

ทำงานโดยการสุ่มตัวอย่างการปฏิเสธ

สร้างตัวเลขสุ่มระหว่าง0ถึง2 ^ 31-1 = 2147483647จนกระทั่งพบน้อยกว่าหนึ่งหรือเท่ากับอินพุต

ฉันรู้สึกราวกับว่าฉันสามารถใช้การตัดแทนสิ่งอื่นได้ แต่ฉันไม่สามารถมองเห็นได้


1
คุณสามารถหลีกเลี่ยงการใช้สิ่งอื่นได้repeatแต่ท้ายที่สุดก็คือ 3 ไบต์ที่ยาวนานกว่า ... ฉันไม่แน่ใจว่ามีวิธีที่สั้นกว่าในการมีคะแนนตัวเลือกแบบไม่ จำกัด กว่าการทำซ้ำ
ลดขนาด

@ กระชับ: ใช่ฉันลองทำซ้ำเช่นกัน ฉันมีความทรงจำในการใช้บางสิ่งบางอย่างเช่น,!.บังคับให้ผู้เล่นย้อนกลับ แต่ฉันจำได้ว่ามันผิดหรือไม่สามารถใช้กับวิธีนี้ได้
Emigna

7

เขาวงกต 63 ไบต์

 ?
 #00}__""*_
 ;    #"  _
{-{=  } "><)
!{ : ;"({ +
@  }}:  >`#

(ขอบคุณ @MartinEnder สำหรับความช่วยเหลือเกี่ยวกับการเล่นกอล์ฟอย่างหนักที่นี่)

เขาวงกตเป็นภาษา 2D และแหล่งที่มาของการสุ่มเท่านั้นที่อยู่ในสถานการณ์เช่นนี้:

   x
  "<)
 " "
 " "

สมมติว่าตัวชี้คำแนะนำอยู่บนxและเลื่อนลง ถัดจากนั้นจะตกลงบน<ซึ่งหากส่วนบนสุดของสแต็กเป็น 0 (ซึ่งเป็นกรณีในโปรแกรมจริงด้านบนเสมอ) เลื่อนแถวปัจจุบันที่เหลือ 1 โดย:

   "
 "<)
 " "
 " "

ตัวชี้คำสั่งอยู่ในขณะ<เคลื่อนที่ลงด้านล่าง ที่ทางแยกเขาวงกตจะเลี้ยวตามด้านบนของสแต็ก - ลบจะเลี้ยวซ้ายบวกจะเลี้ยวขวาและศูนย์จะเดินไปข้างหน้า หากจุดสูงสุดของสแต็คยังคงเป็นศูนย์ ณ จุดนี้เราไม่สามารถเลื่อนไปข้างหน้าหรือข้างหลังเนื่องจากไม่มีเส้นทางดังนั้นเขาวงกตจะสุ่มระหว่างการเลี้ยวซ้ายหรือเลี้ยวขวาด้วยความน่าจะเป็นที่เท่ากัน

โดยเฉพาะอย่างยิ่งสิ่งที่โปรแกรมดังกล่าวข้างต้นไม่สามารถใช้คุณลักษณะการสุ่มเพื่อสร้างตัวเลข 100 บิต (100 ตามที่ระบุไว้#00ที่นี่) <= nและยังคงวนรอบจนกว่าจะสร้างตัวเลข

สำหรับการทดสอบมันอาจจะช่วยในการใช้#0"แทนตัวเลข 10 บิตโดย"เป็นเส้นทางแบบไม่ใช้งาน ลองออนไลน์!

คำอธิบายหยาบ:

 ?            <--- ? is input and starting point
 #0"}__""*_   <--- * here: first run is *0, after that is *2 to double
 ;    #"  _
{-{=  } "><)  <--- Randomness section, +0 or +1 depending on path.
!{ : ;"({ +        After <, the >s reset the row for the next inner loop.
@  }}:  >`#

 ^    ^
 |    |
 |    The " junction in this column checks whether the
 |    100-bit number has been generated, and if not then
 |    continue by turning right into }.
 |
 Minus sign junction here checks whether the generated number <= n.
 If so, head into the output area (! is output as num, @ is terminate).
 Otherwise, head up and do the outer loop all over again.

7

Python ขนาด 61 ไบต์

from random import*
lambda n,x=2.**30:int(randrange(x)*-~n/x)

แก้ไข: อัปเดตเพื่อหลีกเลี่ยงรูปแบบที่ต้องห้าม

แก้ไข 2: บันทึก 2 ไบต์ขอบคุณ @ JonathanAllan

แก้ไข 3: จ่าย 2 ไบต์สำหรับโซลูชันที่ทำงานได้อย่างสมบูรณ์ - ขอบคุณอีกครั้ง @JonathanAllan

แก้ไข 4: ลบf=แล้วบันทึก 2 ไบต์

แก้ไข 5: บันทึกอีก 1 ไบต์ขอบคุณ @ JonathanAllan

แก้ไข 6: บันทึกอีก 2 ไบต์ขอบคุณ @ JonathanAllan

โดยตอนนี้ความผิด git จะชี้มาที่ฉันสำหรับสิ่งที่ไม่ดีและ JonathanAllan สำหรับสิ่งที่ช่วย

แก้ไข 7: เมื่อฝนตกจะเท - อีก 2 ไบต์

แก้ไข 8: และอีก 2 ไบต์


1
เคยชินนี้เคยเอาท์พุทn, แต่คุณสามารถบันทึกไบต์ที่สองเมื่อคุณแก้ไขว่าด้วยการใช้และวางfrom random import* r.
Jonathan Allan

1
ใช่คุณสามารถใช้ "ตัวดำเนินการลูกอ๊อด" เพื่อหลีกเลี่ยงวงเล็บที่จำเป็นเป็นอย่างอื่นดังนั้น...*(-~n*1.0/2**30))แทนที่จะเป็น...*((n+1)*1.0/2**30))
Jonathan Allan

1
จริงๆ? หวาน! คุณมีความขุ่นเคืองที่ยืนยาวต่อหมายเลข 70 หรือไม่? ขอบคุณมากสำหรับความช่วยเหลือของคุณ
iwaseatenbyagrue

1
ในความเป็นจริงrandrangeดูเหมือนว่าจะยอมรับการลอยดังนั้นlambda n,x=2.**30:int(randrange(x)*-~n/x)ช่วยอีกสอง [แก้ไข ... ] สี่!
Jonathan Allan

1
มีอีกสองที่อยู่ในนั้นพร้อมกับการลบวงเล็บ เพียงแค่ไปแสดงการคูณของคุณเป็นวิธีที่จะไป!
Jonathan Allan

6

Python 2 , 61 ไบต์

from random import*
lambda n:map(randrange,range(1,2**31))[n]

หลอกสุ่มเลือกจำนวนเต็มระหว่าง0และkสำหรับค่าทั้งหมดของkระหว่าง0และ2 31 - 2จากนั้นใช้เวลาจำนวนเต็มสอดคล้องกับk = n


5

แบตช์ 64 ไบต์

@set/ar=%random%*32768+%random%
@if %r% gtr %1 %0 %1
@echo %r%

%random%ให้สุ่ม 15 บิตเท่านั้นดังนั้นฉันต้องรวมตัวเลขสุ่มสองตัว ลูปจนกว่าจะมีการสุ่มค่าอยู่ในช่วงที่ต้องการดังนั้นช้าต่ำn; 98 ไบต์สำหรับรุ่นที่เร็วกว่า:

@set/a"n=%1+1,m=~(3<<30)/n*n,r=%random%*32768+%random%
@if %r% geq %m% %0 %1
@cmd/cset/a%r%%%%n%

รหัสอาจช้า แต่คำตอบของคุณรวดเร็ว!

3
@Lembik ผมมีคำตอบพร้อมที่จะไปในคำถามที่ถูกลบของคุณ ...
นีล

สิ่งนี้จะไม่สะท้อนไปยังหมายเลขที่ต้องการก่อนจากนั้นจึงเป็นตัวเลขอื่น ๆ ทั้งหมดที่กลายเป็นใหญ่กว่าn?
Erik the Outgolfer

@EriktheOutgolfer No; ยกเว้นว่าคุณใช้การcallเรียกใช้สคริปต์ชุดงานจะยุติสคริปต์ปัจจุบัน
Neil

5

MATLขนาด 12 ไบต์

ขอบคุณ@AdmBorkBorkและ@Suever ที่บอกวิธีปิดใช้งานแคช TIO

`30WYrqG>}2M

ลองออนไลน์!.

นี้จะใช้วิธีการปฏิเสธ : สร้างจำนวนเต็มสุ่มจาก0ไปและทำซ้ำในขณะที่มันเกินกว่าการป้อนข้อมูล2^30-1 nนี้มีการประกันเพื่อยุติกับความน่าจะ1แต่จำนวนเฉลี่ยของการทำซ้ำเป็น2^30/nและเพื่อให้มันใช้เวลานานมากอย่างมีนัยสำคัญมีขนาดเล็กกว่าn2^30

`         % Do...while
  30W     %   Push 2^30
  Yr      %   Random integer from 1 to 2^30
  q       %   Subtract 1
  G>      %   Does it exceed the input? If so: next iteration. Else: exit
}         % Finally (execute right before exiting the loop)
  2M      %   Push the last generated integer
          % End (implicit). Display (implicit)

4

JavaScript (ES6), 55 54 ไบต์

f=(n,m=1)=>m>n?(x=Math.random()*m|0)>n?f(n):x:f(n,m*2)

สร้างจำนวนเต็มในช่วง[0 ... 2 k - 1]ที่kเป็นที่เล็กที่สุดจำนวนเต็มเช่นที่2 kมีค่ามากกว่าn ซ้ำจนกว่าผลที่ตกอยู่ใน[0 ... n]

ทำไม?

สิ่งนี้อยู่บนพื้นฐานของสมมติฐานต่อไปนี้:

  • ภายในค่าจำนวนเต็มแบบหลอกเทียมที่สร้างขึ้นโดยเอ็นจิน JS เพื่อป้อนข้อมูลMath.random()มีความสม่ำเสมอในช่วงเวลาใด ๆ[0 ... 2 k -1] (ด้วยk <32 )

  • เมื่อคูณด้วยพลังงานที่แน่นอน 2 ค่าลอย IEEE 754 ที่ส่งคืนโดยMath.random()จะยังคงเหมือนกันในช่วงเวลาดังกล่าว

หากใครสามารถยืนยันหรือปฏิเสธสมมติฐานเหล่านี้ได้โปรดแจ้งให้เราทราบในความคิดเห็น

การสาธิต

Generates 1 million values in [0 ... 2] and displays the outcome statistics.


Math.floor(Math.random()*(n+1)) produces a no less uniformly distributed results for me, so it would be nice to see if there is any realistic N < 2^30, which will produce any distribution anomalies at all.
zeppelin

1
@zeppelin you'd need way too many trial runs to pinpoint any anomalies since a random float in that range will have one of 2^53 values which will be distributed as evenly as possible over the 2^30 outcomes. So even for large numbers in the range, the error will be something like 1 in 2^23 which means you'd need a ridiculous number of trials. You'll probably want a few more orders of magnitude than the number of initial samples (2^53). Nevertheless, it can't be perfectly uniform if the multiplier doesn't evenly divide the number of samples which is why Arnauld uses a power of two.
Martin Ender

4

Bash (+coreutils), 44 bytes

/dev/urandom based solution

od -w4 -vtu4</d*/ur*|awk '($0=$2)<='$1|sed q

Will read unsigned 32 bit integers from /dev/urandom, and filter them out with awk until it finds one within a given range, then sed q will abort the pipe.


Hooray for bash :)

4

Haskell, 70 bytes

import System.Random
g n=head.filter(<=n).randomRs(0,2^30)<$>getStdGen

Not a very efficient algorithm but it works. It generates an infinite list of integers (or floats if needed, because of Haskell's type system) bounded by [0,2^30] and takes the first one less than or equal to n. For small n this can take a long time. The random numbers should be uniformly distributed, as specified in the documentation for randomR so all numbers in the interval [0,2^30] should have the same probability (1/(2^30+1)) therefore all the numbers in [0,n] have the same probability.

Alternate Version:

import System.Random
g n=head.filter(<=n).map abs.randoms<$>getStdGen

This version is terrible but it saves a whole byte. randoms uses an arbitrary range defined by the type to generate an infinite list of numbers. This may include negatives so we need to map it with abs to force them positive (or zero). This is extremely slow for any values of n that aren't absurdly large. EDIT: I realized later that this version isn't uniformly distributed because the probability of getting 0 is worse than the other numbers due to the use of abs. To produce some number m the generator could produce m or -m but in the case of 0 only 0 itself will work, therefore its probability is half of the other numbers.


Hooray for Haskell (too)!

4

Jelly, 9 bytes

⁴!Ẋ’>Ðḟ⁸Ṫ

Try it online! - code above wont run on TIO since a range of size 16! must be built first (not to mention the fact that they then need to be shuffled and then filtered!), so this is the same thing on a much smaller scale, repeated 30 times for an input of 3 with a bound of 10.

How?

⁴!Ẋ’>Ðḟ⁸Ṫ - Main link: n
⁴         - 16
 !        - factorial: 20922789888000
  Ẋ       - shuffle random: builds a list of the integers 1 through to 16! inclusive and
          - returns a random permutation via Python's random.shuffle (pretty resource hungry)
   ’      - decrement (vectorises - a whole pass of this huge list!)
     Ðḟ   - filter out if: (yep, yet another pass of this huge list!)
    >     -     greater than
       ⁸  -     left argument, n
        Ṫ - tail: return the rightmost remaining entry.

Note: it would be over a thousand time more efficient for the same byte-count if ȷ⁵ would do what one would naively expect and return ten to the ten, but that is not the case since the is not evaluated as a literal ten to be used by the number literal ȷ... but rather two separate literals are parsed, ȷ with it's default exponent of three yielding one thousand, and yielding ten.


Huh, thats 9 characters, but 22 bytes
Kristoffer Sall-Storgaard

@KristofferSall-Storgaard Each character is one of the 256 bytes in Jelly's code page, I forgot to make the word bytes a link like I usually do.
Jonathan Allan

1
year, I looked it up and found out the same
Kristoffer Sall-Storgaard

4

JDK 9 on jshell, 75 59 bytes

n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny()

Usage

((IntFunction)(n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny())).apply(<n>)
  • -16 bytes: Thanks Jakob!
  • Assumes that we consider jshell to be a valid runtime environment.
  • jshell itself, as a runtime environment, doesn't require explicit imports for core libraries and doesn't require semicolons.
  • Returns an OptionalInt. Rules don't specify that return type must be a primitive and I'm considering an OptionalInt to be a valid representation of the result.

1
Thanks to @kevin-cruijssen for the inspiration. My first code golf!
Pete Terlep

Whether or not boxed output is accepted is different from whether an Optional is accepted. I would confirm with the poster if I were you. Also, no need to count the whole assignment; just the lambda expression is sufficient.
Jakob

1
You can save 4 bytes by removing parentheses around lambda parameter n and new Random().
Jakob

3

PHP, 30 bytes

    while($argn<$n=rand());echo$n;

Run with echo <N> | php -Rn '<code>'.

picks a random number between 0 and getrandmax() (2**31-1 on my 64 bit machine);
repeats while that is larger than the input.

This may take a while ... my AMD C-50 (1 GHz) needed between 0.3 and 130 seconds for N=15.

A faster way for average N (46 bytes):

for(;++$i<$x=1+$argn;)$n+=rand()%$x;echo$n%$x;

or

for(;++$i<$x=1+$argn;$n%=$x)$n+=rand();echo$n;

takes N+1 random integers, sums them up and takes the modulo with N+1.
The C-50 needs approx. 8 seconds for 1 million runs.

An invalid solution for 19 bytes:

echo rand(0,$argn);

3

PowerShell, 35 bytes

for(;($a=Random 1gb)-gt"$args"){}$a

Try it online!

Another rejection sampling method. This is an infinite for loop, setting the value of $a to be a Random integer between 0 and 1gb (= 1073741824 = 2^30), and keeps looping so long as that integer is -greaterthan the input $args. Once the loop is complete, we just put $a on the pipeline and output is implicit.

Note: This will take a long time if the input is a small number.


3

Python 2, 72 69 bytes

-3 bytes thanks to xnor (override the id built-in as a variable)

from random import*
n=input()
while id>n:id=randrange(2**30)
print id

Try it online!

randrange(2**30) produces a pseudo-uniformly distributed number (Mersenne Twister 219937-1) from the range [0,230). Since n is guaranteed to be below 230 this can simply be called repeatedly until it is not greater than the input. It will take a long expected time for very low values of n, but usually works within the a minute even for inputs as low as 50.


2
You can initialize r='' as "infinity". Or, better yet, don't initialize r and instead use id everywhere for r.
xnor


2

05AB1E, 11 bytes

žIÝ.rDI›_Ϥ

Try it online!

Explanation

žIÝ          # push the inclusive range [0 ... 2^31]
   .r        # get a random permutation (pythons random.shuffle)
     D       # duplicate this list
      I      # push input
       ›_Ï   # keep only elements from the list not greater than input
          ¤  # take the last one

As the list [0 ... 2147483648] is too large for TIO, the link uses 1.000.000 instead.

Alternate (on average) much faster 11 byte solution

[žIÝ.RD¹›_#

Try it online

Explanation

[             # start loop
 žIÝ          # push the inclusive range [0 ... 2^31]
    .R        # pick a random integer (pythons random.chiose)
      D       # duplicate
       ¹      # push input
        ›_#   # break if random number is not greater than input
              # implicitly output top of stack (the random number)

žJL.R% for 6 unless I'm missing something huge. Push 2^32, list from 0 to 2^32, random pick. Modulo input. Will absolutely screw the efficiency that you have.
Magic Octopus Urn

@carusocomputing.You'd need an I in there for 7 bytes to get the arguments for modulus in the right order (and maybe Ý instead of L), but otherwise that's certainly a shorter solution. I saw Dennis doing that in his Jelly answer, but as this was my first idea I kept this. As that approach is different from this you could post it as a separate answer.
Emigna

DI‹Ï would avoid the loop.
Magic Octopus Urn

Also, as-is, this is not guaranteed to terminate; if I'm not mistaken, an input of 0 would almost always result in a near-infinite loop, making it hard to terminate. Though the solution does allow for the possibility to terminate in all scenarios it isn't guaranteed due to randomness.
Magic Octopus Urn

@carusocomputing: For very small input the second version would on average take a very long time to finish yes, but given enough time it would.
Emigna

2

Python 2, 89 bytes

l=range(2**31)
import random
random.shuffle(l)
n=input()
print filter(lambda x:x<=n,l)[0]

Explanation

L=range(2**31)      # Create a list from 0 to 2^31 exclusive. Call it <L>.
import random       # Import the module <random>.
random.shuffle(L)   # Use 'shuffle' function from <random> module,
                    # to shuffle the list <L>.
n=input()           # Take the input -> <n>.

print
    filter(         # Create a new sequence,
    lambda x:x<=n   # where each element is less than or equal to <n>.
    ,L)             # from the list <L>.
    [0]             # Take the first element.

This is very inefficient, as it creates 2^31 integers, shuffles and filters them.

I see no point in sharing a TIO link, where it's creating such large lists, so here is a TIO link for n = 100.

Try it online!


2

Java 8, 84 83 80 71 62 bytes

n->{int r;for(;(r=(int)(Math.random()*(1<<30)))>n;);return r;}

-1 byte thanks to @OliverGrégoire.
-3 bytes thanks to @Jakob.
-9 bytes converting Java 7 to Java 8.
-9 bytes by changing java.util.Random().nextInt(1<<30) to (int)(Math.random()*(1<<30)).

Explanation:

Try it here.

n->{        // Method with integer parameter and integer return-type
  int r;    //  Result-integer
  for(;(r=(int)(Math.random()*(1<<30)))>n;);
            //  Loop as long as the random integer is larger than the input
            //  (the random integer is in the range of 0 - 1,073,741,824 (2^30))
  return r; //  Return the random integer that is within specified range
}           // End method

NOTE: May obviously take very long for small inputs.

Example output:

407594936

2
@Aaron I questioned this as well but see the second bullet point: "Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value." This is the reason max int is used.
Poke

1
2^30 = 1073741824. You preferred to use -1>>>1 (= 2147483647). But this exists: 1<<30 which is exactly equals to 2^30; and is 1 byte shorter.
Olivier Grégoire

1
How about int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}?
Jakob

@Jakob Thanks. I even shortened it by 18 more bytes by using Java 8 instead of 7, and using Math.random() instead of java.util.Random().nextInt.
Kevin Cruijssen

2

Python 3, 51 bytes

Here is a python solution with an unorthodox random source.

print(list(set(map(str,range(int(input())+1))))[0])

Try it online!

So to break this down.

int(input())+1

Gets the input number, and adds 1 to it.

set(range(...))

Creates the set {0, 1, 2, 3, 4, ... n} for all possible results.

print(list(...)[0])

Takes the set, converts it to list, and grabs the first item.

This works because in Python 3, the order of set() is established by PYTHONHASHSEED (can't be obtained but is established on script execution).

Admittedly, I am guessing that this is a uniform distribution, as the hash() value is randomly assigned and I am looking at randomly picking the value with a specific hash(), rather then just returning the hash(input()) itself.

If anyone knows whether this is a uniform distribution, or how I could test that, please comment.


1

C#, 57 bytes

n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

Anonymous function which returns an integer between 0 and n inclusive.

The smaller the input number, the longer the time to return a random value.

Full program:

using System;

class RandomNumber
{
    static void Main()
    {
        Func<int, int> f =
        n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

        // example
        Console.WriteLine(f(100000));
    }
}

2
"Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value." The argument to Next is not static.
Yytsi

1

Bash + coreutils, 20 bytes

Golfed

seq 0 $1|shuf|sed 1q

shuf - generate random permutations

Shuf will use the following code: to generate permutations:

permutation = randperm_new (randint_source, head_lines, n_lines);

which ends up in randint_genmax

/* Consume random data from *S to generate a random number in the range
0 .. GENMAX.  */

randint
randint_genmax (struct randint_source *s, randint genmax) 
{
      ...

      randread (source, buf, i);

      /* Increase RANDMAX by appending random bytes to RANDNUM and
         UCHAR_MAX to RANDMAX until RANDMAX is no less than
         GENMAX.  This may lose up to CHAR_BIT bits of information
         if shift_right (RANDINT_MAX) < GENMAX, but it is not
         worth the programming hassle of saving these bits since
         GENMAX is rarely that large in practice.  */
      ...
}

which, in turn, will read a few bytes of the random data from the low-level source of randomness:

/* Consume random data from *S to generate a random buffer BUF of size
   SIZE.  */

void
randread (struct randread_source *s, void *buf, size_t size)
{
  if (s->source)
    readsource (s, buf, size);
  else
    readisaac (&s->buf.isaac, buf, size);
}

i.e. at the low-level, there is no direct dependency between the shuf input value and the data read from the source of randomness (aside from computing the required byte buffer capacity).


6
Isn't this giving the input as an argument to your random number generator?
Martin Ender

Even if this is not valid, please submit another bash answer!

@MartinEnder well, not directly, it just uses the input to define the upper limit for the generated integer range and jot will arrange for all the values in the range to appear in the output with an equal probability (that's probably borderline, but still).
zeppelin

2
If I dig deep enough into any random number generator I'm sure I'll find a call into a lower-level RNG that doesn't directly use the original argument. The point of the challenge is to obtain an arbitrary-size uniform distribution from a fixed -size distribution, which you're still not doing.
Martin Ender


1

Ruby, 23 15 23 32 29 bytes

->n{1while n<q=rand(2**30);q}

How it works:

  • 1while [...]; executes the statement at least once: 1 before while acts as a nop
  • Get a random number in the range 0..2^30-1 (lower than 2^30, as specified)
  • Repeat if the number is higher than the input parameter (Could take some time when n is small)

1

Ohm, 26 bytes

IΩ
D31º#╬D0[>?D-+∞;,

Explanation:

IΩ                 ■Main wire
IΩ                 ■Call wire below

D31º#╬D0[>?D-+∞;,  ■"Real main" wire
D                  ■Duplicate input
 31º#╬D            ■Push random_int in [0..2^31] twice
       0[          ■Push input again
         >?    ;   ■If(random_int > input){
           D-+     ■  remove the random_int
              ∞    ■  recursion
               ;   ■}
                ,  ■Print random_int

Is there an interpreter for this language? And what about Code-page?
ATaco

@ATaco: Interpreter, Code-page: CP-437
Emigna


1

Golang, 84 78 71 bytes

import."math/rand"
func R(n int)int{q:=n+1;for;q>=n;q=Int(){};return q}

Simple rejection sampling.

Note: since the math/rand seed is a constant 1, the caller must seed unless a constant result is desired.

Test: https://play.golang.org/p/FBB4LKXo1r No longer practically testable on a 64-bit system, since it's returning 64-bit randomness and using rejection testing.

package main

import "fmt"
import "time"

/* solution here *//* end solution */

func main() {
    Seed(time.Now().Unix())
    fmt.Println(R(1073741823))
}

1
if you use import."math/rand" then Int31 is available in the global namespace and you can save 4 bytes, also intis guaranteed to be at least 32 bits, saving you another 6 bytes
Kristoffer Sall-Storgaard

Use := syntax for another 3 bytes
Kristoffer Sall-Storgaard

Using int instead of int32 doesn't save any bytes since we need to cast the result of Int31() - 3*int + () = 11 bytes versus 2*int32 = 10 bytes.
Riking

1
No need to cast, there is an Int() function in the rand package, also, you can remove the space after import
Kristoffer Sall-Storgaard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.