การจำลองการกระจายลูกเต๋า


31

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

เมื่อคุณหมุนแม่พิมพ์ให้ตรวจสอบค่าที่คุณสะสม หากคุณมีค่าสูงสุดสำหรับการตายชนิดนั้น (บน d4 มาตรฐานที่จะเป็น 4 หรือ 6 ใน d6 เป็นต้น) ให้หมุนอีกครั้งและเพิ่มการม้วนใหม่ไปยังผลรวมนั้น แต่ละม้วนจะเพิ่มไปยังผลรวมจนกว่าคุณจะไม่หมุนหมายเลขสูงสุดอีกต่อไป หมายเลขสุดท้ายนั้นยังคงถูกเพิ่มเข้ามา

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

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


1
โปรแกรมจำเป็นต้องสมบูรณ์แบบหรือไม่ เช่นเดียวกับการกระจายของมันจะถูกปิดโดยบางส่วนที่ต่ำมาก?
Maltysen

ถึง: Riker; RE: @ ความคิดเห็นของ Maltysen ด้านบน; หรือจำนวนที่สูงมาก?
อาร์ทิมิสรองรับโมนิก้า

คำตอบ:


36

x86 รหัสเครื่อง (สำหรับ Intel Ivy Bridge และใหม่กว่า), 17 ไบต์

31 C9 0F C7 F0 31 D2 F7 F6 42 01 D1 39 F2 74 F2 C3

ไบต์ของโค้ดด้านบนจะกำหนดฟังก์ชั่นที่จำลองการตายของการระเบิด ใช้อินพุตเดียวส่งผ่านในESIรีจิสเตอร์เพื่อระบุจำนวนสูงสุดของการตาย มันส่งกลับค่าเดียวในการECXลงทะเบียนซึ่งเป็นผลมาจากการม้วน

ภายในจะใช้การเรียนการสอนเพื่อสร้างตัวเลขสุ่ม สิ่งนี้ใช้ตัวสร้างตัวเลขสุ่ม (RNG) ที่สร้างไว้ในฮาร์ดแวร์ของโปรเซสเซอร์ Intel Ivy Bridge และใหม่กว่า (ซีพียู AMD บางรุ่นยังรองรับคำสั่งนี้)RDRAND

ตรรกะของฟังก์ชันนั้นค่อนข้างตรงไปตรงมา จำนวนสุ่มที่สร้างขึ้นจะถูกปรับให้อยู่ในช่วงที่ต้องการโดยใช้เทคนิคมาตรฐาน ( (rand % dieSize) + 1) จากนั้นจะมีการตรวจสอบเพื่อดูว่าควรจะทำให้เกิดการระเบิดหรือไม่ ผลสุดท้ายจะถูกเก็บไว้ในบันทึกการสะสม

นี่คือรุ่นที่มีคำอธิบายประกอบแสดงตัวช่วยจำภาษาแอสเซมบลี:

           unsigned int RollExplodingDie(unsigned int dieSize)
31 C9        xor     ecx, ecx    ; zero-out ECX, which accumulates the final result
           Roll:
0F C7 F0     rdrand  eax         ; generate a random number in EAX
31 D2        xor     edx, edx    ; zero-out EDX (in preparation for unsigned division)
F7 F6        div     esi         ; divide EDX:EAX by ESI (the die size)
                                 ;   EAX receives the quotient; EDX receives the remainder
42           inc     edx         ; increment the remainder
01 D1        add     ecx, edx    ; add this roll result to the accumulator
39 F2        cmp     edx, esi    ; see if this roll result should cause an explosion
74 F2        jz      Roll        ; if so, re-roll; otherwise, fall through
C3           ret                 ; return, with result in ECX register

ฉันกำลังโกงนิด อนุสัญญาการเรียกมาตรฐาน x86 ทั้งหมดส่งคืนผลลัพธ์ของฟังก์ชันในการEAXลงทะเบียน แต่ในรหัสเครื่องที่แท้จริงไม่มีการเรียกประชุม คุณสามารถใช้รีจิสเตอร์ที่คุณต้องการสำหรับอินพุต / เอาต์พุต ใช้ECXสำหรับการลงทะเบียนเอาท์พุทบันทึกฉัน 1 ไบต์ หากคุณต้องการใช้EAXให้ใส่XCHG eax, ecxคำสั่งขนาด 1 ไบต์ทันทีก่อนretคำสั่ง แลกเปลี่ยนนี้ค่าของEAXและECXลงทะเบียนได้อย่างมีประสิทธิภาพการคัดลอกผลจากECXเข้าEAXและ trashing มีค่าเก่าECXEAX

ลองออนไลน์!

นี่คือฟังก์ชั่นเทียบเท่าคัดลอกใน C โดยใช้ภายในได้รับการสนับสนุนโดย GCC, เสียงดังกราวและ ICC เพื่อสร้างการเรียนการสอน:__builtin_ia32_rdrand32_stepRDRAND

#include <immintrin.h>

unsigned int RollExplodingDie(unsigned int dieSize)
{
    unsigned int result = 0;
Roll:
    unsigned int roll;
    __builtin_ia32_rdrand32_step(&roll);
    roll    = ((roll % dieSize) + 1);
    result += roll;
    if (roll == dieSize)   goto Roll;
    return result;
}

ที่น่าสนใจGCC กับ-Osธงแปลงนี้ในเกือบตรงรหัสเครื่องเดียวกัน ใช้อินพุตEDIแทนESIซึ่งเป็นกฎเกณฑ์โดยสมบูรณ์และไม่มีการเปลี่ยนแปลงเกี่ยวกับรหัส มันจะต้องกลับผลในการEAXที่ผมกล่าวถึงก่อนหน้านี้และจะใช้อย่างมีประสิทธิภาพมากขึ้น ( แต่มีขนาดใหญ่) การเรียนการสอนการทำเช่นนี้ทันทีก่อนMOV RETมิฉะนั้น Samezies มันสนุกเสมอเมื่อกระบวนการสามารถย้อนกลับได้อย่างเต็มที่: เขียนโค้ดในชุดประกอบถอดความเป็น C เรียกใช้ผ่านคอมไพเลอร์ C และนำชุดประกอบดั้งเดิมของคุณออกมา!


12

Python 2 , 66 64 61 ไบต์

-3 ไบต์ขอบคุณ xnor

f=lambda n,c=0:c%n or c+f(n,randint(1,n))
from random import*

ลองออนไลน์!

ม้วนก่อนหน้านี้ถูกเก็บไว้ใน cทำให้เราสามารถเข้าถึงได้หลายครั้งโดยไม่ต้องเก็บไว้ในตัวแปรซึ่งไม่สามารถทำได้ใน Python แลมบ์ดา การสอบถามซ้ำแต่ละครั้งเราตรวจสอบว่าเรากลิ้งลูกเต๋าระเบิดหรือไม่

c ถูกกำหนดค่าเริ่มต้นเป็นศูนย์ดังนั้น c%nมีความเท็จ ในการทำซ้ำครั้งต่อไปมันจะเป็นเท็จถ้าระเบิดลูกเต๋าถูกรีด

Python 2 , 55 ไบต์

f=lambda n:randint(1,n)%n or n+f(n)
from random import*

ลองออนไลน์!

คำตอบอื่น ๆ ของฉันดูเหมือนจะถูก overengineered เล็กน้อยตั้งแต่นี้ดูเหมือนจะทำงานได้ดี ... ฉันจะทิ้งมันไว้


2
ฟังก์ชั่นแบบเรียกซ้ำที่เงื่อนไขการทำลายอ้างอิงตามการสุ่มจะมีโอกาสที่ไม่เป็นศูนย์ในการล้นสแต็ก โอกาสที่ไม่มีนัยสำคัญทางสถิติ แต่ยัง ...
mypetlion

3
โดยทั่วไปแล้วขนาดสแต็คจะถือว่าไม่มีที่สิ้นสุดในการแข่งขันกอล์ฟโค๊ดในประสบการณ์ของฉัน เมื่อขนาดสแต็คเพิ่มขึ้นเป็นระยะอินฟินิตี้โอกาสของการโอเวอร์โฟลว์แบบสแต็กจะแปรสภาพเป็นศูนย์อย่างรวดเร็ว
ArBo

ArBo do @mypetlion ก่อนที่คุณจะพิมพ์ความคิดเห็นของคุณเพื่อให้คุณสามารถ ping ผู้ใช้
MilkyWay90

1
ผมคิดว่าอาจจะเป็นc*(c<n) c%n
xnor

@xnor แน่นอนฉันเป็นคนงี่เง่า ...
ArBo

12

R , 39 ไบต์

n=scan();n*rgeom(1,1-1/n)+sample(n-1,1)

ลองออนไลน์!

คำอธิบาย: วิธีนี้หลีกเลี่ยงการเรียกซ้ำ / ในขณะที่ลูปโดยคำนวณการกระจายของจำนวนการระเบิดที่จะเกิดขึ้นโดยตรง ให้nเป็นจำนวนด้านในการตาย หากคุณแสดงถึงความสำเร็จในการกลิ้งตัวnและความล้มเหลวเหมือนกับการหมุนสิ่งอื่นคุณก็มีโอกาส1nประสบความสำเร็จ จำนวนการระเบิดทั้งหมดคือจำนวนความสำเร็จก่อนที่ความล้มเหลวครั้งแรก สอดคล้องนี้ให้Gอีโอม.อีเสื้อRผม(1-1n)การแจกจ่าย (ดูที่หน้าวิกิพีเดียซึ่งกำหนดความสำเร็จและความล้มเหลวในทางกลับกัน) แต่ละระเบิดนำnไปทั้งหมด ม้วนสุดท้ายดังนี้ยูnผมโอRม.(1,2,...,n-1)การกระจายที่เราเพิ่มไปทั้งหมด


ดีมาก! ต้องรักการกระจายภายในสำหรับความท้าทายแบบสุ่ม !
จูเซปเป้

เป็นsampleไปตามมาตรฐานสำหรับการสุ่มได้รับอคติหรือไม่
ซีอาน

@ ซีอานค่อนข้างแน่ใจว่ามัน : มันเป็นตัวกำเนิดแบบสุ่มในตัวสำหรับตัวแปรสุ่มแบบแยก
Robin Ryder

ฉันรู้ว่าฉันรู้ แต่ตรวจสอบลิงก์ที่ฉันใส่: การแยกส่วนโดยธรรมชาติจะsampleนำไปสู่การขาดความสม่ำเสมอที่ให้อัตราส่วนของความน่าจะเป็นสูงสุดต่อนาทีที่สูงถึง 1.03 ... น่าตกใจใช่มั้ย!
ซีอาน

ใช่มันเป็นเรื่องที่น่าตกใจ แต่แล้วอีกครั้งอย่างไรคุณมักจะใช้sampleกับ ? ;-)ม.2วันที่ 31
Robin Ryder

9

Perl 6 , 26 ไบต์

{sum {roll 1..$_:}...*-$_}

ลองออนไลน์!

คำอธิบาย

{                        } # Anonymous block
                  ...      # Sequence constructor
     {roll 1..$_:}         #   Next elem is random int between 1 and n
                           #   (Called as 0-ary function with the original
                           #   $_ for the 1st elem, then as 1-ary function
                           #   with $_ set to the previous elem which
                           #   equals n.)
                     *-$_  #   Until elem not equal to n (non-zero difference)
 sum                       # Sum all elements

2
Nice, ทางออกของฉันคือ{sum roll(*,1..$_)...$_>*}
Jo King

9

J , 16 11 ไบต์

(+$:)^:=1+?

ลองออนไลน์!

คำอธิบาย

TL; DR 1+?ทำการรีดตาย, จะทำ(+$:)^:=ซ้ำเฉพาะเมื่อเท่ากับอินพุต


ฟังก์ชั่นเป็นขบวนคำกริยา 4 คำ:

             ┌─ + 
         ┌───┴─ $:
  ┌─ ^: ─┴─ =     
  │               
──┤      ┌─ 1     
  └──────┼─ +     
         └─ ?     

รถไฟคือเมื่อมีคำกริยา 2 ตัวหรือมากกว่าถูกต่อกัน นี่คือคำตอบของแบบฟอร์มf g h j:

(+$:)^:=  1  +  ?
    f     g  h  j

สิ่งที่เรียกว่า "4 รถไฟ" จะถูกแยกวิเคราะห์เป็นเบ็ดและส้อม:

f g h j   ⇔   f (g h j)

ดังนั้นคำตอบจึงเท่ากับ:

(+$:)^:= (1 + ?)

Hooks: (f g) xและx (f g) y

monadic hook (one-argument) ของคำกริยาสองตัวที่ได้รับการโต้แย้งxการเทียบเท่าต่อไปนี้ถือ

(f g) x   ⇔   x f (g x)

ยกตัวอย่างเช่นการ(* -) 5ประเมินซึ่งประเมิน5 * (- 5)_25

ซึ่งหมายความว่ารถไฟ 4 ขบวนของเรามีระบบfและ(g h j)เทียบเท่ากับ:

(f (g h j)) x   ⇔   x f ((g h j) x)

แต่ที่fนี่ทำอะไร (+$:)^:=คือการรวมกันของคำกริยาสองคำโดยใช้การรวมพลัง^: : ตะขออีกอัน ( (+$:)) และกริยา ( =) โปรดทราบว่านี่fคือdyadic - มีสองอาร์กิวเมนต์ ( xและ(g h j) x) ดังนั้นเราต้องดูว่ามัน^:มีพฤติกรรมอย่างไร การรวมพลังf^:oจะใช้กริยาfและทั้งกริยาหรือคำนามo(นามเป็นเพียงส่วนหนึ่งของข้อมูล) และใช้f oเวลา o = 3ตัวอย่างเช่นใช้ ความเท่าเทียมกันดังต่อไปนี้ถือ:

(f^:3) x     ⇔   f (f (f x))
x (f^:3) y   ⇔   x f (x f (x f y))

ถ้าoเป็นคำกริยาการรวมพลังจะประเมินoเหนือข้อโต้แย้งและใช้ผลลัพธ์คำนามเป็นจำนวนซ้ำ

สำหรับคำกริยาของเราoคือ=กริยาที่เท่าเทียมกัน มันประเมินเพื่อ0หาข้อโต้แย้งที่แตกต่างและ1สำหรับข้อโต้แย้งที่เท่าเทียมกัน เราทำซ้ำฮุก(+$:)หนึ่งครั้งเพื่อหาข้อโต้แย้งที่เท่าเทียมกันและไม่มีเวลาสำหรับคำที่ต่างกัน y ⇔ ((g h j) x)เพื่อความสะดวกในสัญกรณ์สำหรับคำอธิบายให้ โปรดจำไว้ว่าตะขอเริ่มต้นของเราเทียบเท่ากับสิ่งนี้:

x   (+$:)^:=   ((g h j) x)
x   (+$:)^:=   y

การขยายการรวมนี่จะกลายเป็น:

x ((+$:)^:(x = y)) y

หากxและyเหมือนกันสิ่งนี้จะกลายเป็น:

x (+$:)^:1 y   ⇔   x (+$:) y

มิฉะนั้นจะกลายเป็น:

x (+$:)^:0 y   ⇔   y

ตอนนี้เราได้เห็นส้อมแบบ monadic แล้ว ที่นี่เรามีส้อมส้อม:

x (f g) y   ⇔   x f (g y)

ดังนั้นเมื่อxและyเหมือนกันเราจะได้รับ:

x (+$:) y   ⇔   x + ($: y)

คือ$:อะไร มันหมายถึงคำกริยาทั้งหมดและช่วยให้การเรียกซ้ำ ซึ่งหมายความว่าเมื่อใดxและ y are the same, we apply the verb toy and addx` ไป

Forks: (g h j) x

ตอนนี้ส้อมด้านในทำอะไร? นี่เป็นyตัวอย่างสุดท้ายของเรา สำหรับ monadic fork ของคำกริยาสามตัว, ได้รับการโต้แย้งx, การระงับความเสมอกันดังต่อไปนี้:

(g h j) x   ⇔   (g x) h (j x)

ตัวอย่างต่อไปนี้สมมติว่าเรามีคำกริยาชื่อSUM, DIVIDEและLENGTHซึ่งทำในสิ่งที่คุณคิดว่าพวกเขาอาจจะ หากเราต่อสามสิ่งเข้าด้วยกันเราจะได้:

(SUM DIVIDE LENGTH) x   ⇔   (SUM x) DIVIDE (LENGTH x)

ทางแยกนี้ประเมินค่าเฉลี่ยของx(สมมติว่าxเป็นรายการของตัวเลข) ใน J +/ % #เราต้องการจริงเขียนนี้เป็นตัวอย่างเป็น

สิ่งสุดท้ายที่เกี่ยวกับส้อม เมื่อ "Tine" ซ้ายสุด (ในกรณีที่เป็นสัญลักษณ์ของเราด้านบนg) เป็นคำนามคำสั่งจะถือว่าเป็นฟังก์ชันคงที่ที่ส่งคืนค่านั้น

ด้วยสิ่งเหล่านี้ทั้งหมดเราสามารถเข้าใจทางด้านบน:

(1 + ?) x   ⇔   (1 x) + (? x)
            ⇔   1 + (? x)

?[0,x)[1,x]

วางมันทั้งหมดเข้าด้วยกัน

เมื่อรับทุกสิ่งเหล่านี้คำกริยาของเราเทียบเท่ากับ:

((+$:)^:=1+?) x   ⇔   ((+$:)^:= 1 + ?) x
                  ⇔   ((+$:)^:= (1 + ?)) x
                  ⇔   x ((+$:)^:=) (1 + ?) x
                  ⇔   x ((+$:)^:=) (1 + (? x))
                  ⇔   x (+$:)^:(x = (1 + (? x))
(let y = 1 + (? x))
if x = y          ⇒   x + $: y
otherwise         ⇒   y

เป็นการแสดงออกถึงฟังก์ชั่นที่ต้องการ


1
(+$:)^:=1+?­­
ngn

@ngn ขอบคุณ! Incorporated
Conor O'Brien

7

เยลลี่ขนาด 7 ไบต์

X+ß}¥=¡

ลองออนไลน์!

ใช้การเรียกซ้ำ รันโปรแกรมอีกครั้ง ( ß) และเพิ่ม ( +) ถ้า ( ¡) ตัวเลขสุ่ม ( X) เท่ากับ ( =) ไปยังโปรแกรมอินพุต }ทำให้การßทำงานกับโปรแกรมอินพุตและ¥รวม+ß}เป็นลิงค์เดียวสำหรับ¡การบริโภค

นี่คือการกระจาย 1000 ผลสำหรับ n = 6 ซึ่งผมเก็บรวบรวมใช้นี้โปรแกรม พล็อตด้วย python / matplotlib histogram

นี่คือจุดข้อมูล 5000 จุดจาก n = 3 บนพล็อต semilog ซึ่งแสดงการแจกแจงเอ็กซ์โพเนนเชียล (โดยประมาณ) ป้อนคำอธิบายรูปภาพที่นี่


แผนการที่ดี! การแจกแจงที่คุณได้รับคือการแจกแจงเชิงเรขาคณิต (ดูคำตอบ R ของฉัน ) ซึ่งเกี่ยวข้องอย่างใกล้ชิดกับการแจกแจงเอ็กซ์โพเนนเชียล
Robin Ryder

6

Pyth - 12 11 ไบต์

ใช้งานได้ในขณะที่ ฉันรู้สึกว่าควรมีคำตอบที่ชาญฉลาดกว่าที่จะจำลองการกระจายตัว

-.W!%HQ+hOQ

-         (Q)         Subtract Q. This is because we start Z at Q to save a char
 .W                   While, functionally
  !                   Logical not. In this case, it checks for 0
   %HQ                Current val mod input
  +     (Z)           Add to current val
   h                  Plus 1
    OQ                Random val in [0, input)

ลองมันออนไลน์


4

Python 3 , 80 ไบต์

import random as r,math
lambda n:int(-math.log(r.random(),n))*n+r.randint(1,n-1)

ลองออนไลน์!


1
มีโอกาสเล็กน้อยสำหรับความล้มเหลวหากr.random()เกิดขึ้นกับผลตอบแทน 0 1-r.random()ควรทำงาน
nwellnhof

แม้ว่าในทางเทคนิคแล้วโอกาสนั้นคือ 0
Quintec

1
กรณีที่หายากซึ่งimport ... as _สั้นที่สุด!
xnor

@xnor แน่นอน! เวลาอื่นเท่านั้นที่ฉันจำได้ว่าการชนะคำตอบของฉันอยู่ที่นี่
ลินน์

4

05AB1E , 10 ไบต์

[ILΩDIÊ#}O

ลองออนไลน์หรือตรวจสอบรายชื่อ

ทางเลือก 10 ไบต์:

[LΩDˆÊ#}¯O

ลองออนไลน์หรือตรวจสอบรายชื่อ

แม้ว่าฉันจะชอบอันดับหนึ่งมากกว่าเพราะมี 'คำ' DIÊอยู่ในนั้นซึ่งเหมาะกับความท้าทาย

คำอธิบาย:

[         # Start an infinite loop:
 IL       #  Create a list in the range [1, input]
   Ω      #  Pop and push a random value from this list
    D     #  Duplicate it
     IÊ   #  If it's NOT equal to the input:
       #  #   Stop the infinite loop
}O        # After the loop: sum all values on the stack
          # (which is output implicitly as result)

[         # Start an infinite loop
 L        #  Create a list in the range [1, (implicit) input]
  Ω       #  Pop and push a random value from this list
   Dˆ     #  Add a copy to the global_array
     Ê    #  If it's NOT equal to the (implicit) input:
      #   #   Stop the infinite loop
        # After the loop: push the global_array
  O       # Pop and push its sum
          # (which is output implicitly as result)  

กำลังพยายามคิดหาวิธีใช้หรือบางสิ่งบางอย่าง
Magic Octopus Urn


3

R , 47 42 ไบต์

function(n){while(!F%%n)F=F+sample(n,1)
F}

ลองออนไลน์!

ให้เครดิตกับแนวทางของ ArBoวิธี

ยังเป็นไบต์ที่ยาวกว่าของRobin Ryderไปเลยโหวตขึ้น!


น่าสนใจฉันทำใหม่นี้เป็นแบบเรียกซ้ำif46 ไบต์ แต่จบลงด้วยการได้ 52 ในหนึ่งม้วนซึ่งไม่น่าจะเป็นไปได้ด้วย n = 4 ดังนั้นฉันไม่รู้ว่ามีข้อ จำกัด การเกิดซ้ำที่ต่ำแปลก ๆ แต่ฉัน คิดว่ามันอาจจะบั๊ก ลองออนไลน์!
CriminallyVulgar

ฉันลองใช้ recursive และได้โซลูชัน 54 ไบต์ ลองสิ่งที่คล้ายกับของคุณสำหรับ 44 ลองออนไลน์!
แอรอนเฮย์แมน



3

Haskell , 77 76 ไบต์

import System.Random
f x=randomRIO(1,x)>>=(x!)
x!y|y<x=pure y|0<1=(y+)<$>f x

ลองออนไลน์!

ขอบคุณ killmous หนึ่งไบต์

ถ้า<|>อยู่ในบทโหมโรงเราก็ทำได้ดีกว่าด้วยMonadComprehensions :

Haskell ที่ไม่ใช่การแข่งขัน 66 ไบต์

import System.Random
f x=do y<-randomRIO(1,x);[y|y<x]<|>(y+)<$>f x

ลองออนไลน์!


1
คุณสามารถบันทึกไบต์ถ้าคุณกำหนด g เป็นฟังก์ชั่นมัด
killmous

1
@killmous ขอบคุณ ฉันคิดว่ามันจะเหมือนเดิมหรือแย่กว่านั้น แต่ก็ดีกว่า
dfeuer

3

Python 2 , 53 ไบต์

f=lambda n:random()*n//1or n+f(n)
from random import*

ลองออนไลน์!

ใช้orความคิดการลัดวงจรจากคำตอบของ Arbo การแสดงออกที่random()*n//1สร้างตัวเลขจาก0การn-1ที่มีการใช้สถานที่ของม้วนที่0 เตะตัวเลขที่ยกเว้นถ้าเป็นศูนย์ (Falsey) ก็ยังคงไปnorn+f(n)


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


3

Japt , 13 ไบต์

ö)g@¶°X?X+ß:X

ลองมัน

คำตอบของพอร์ตของArnauldคำตอบคิดวิธีการโทรซ้ำ;)

transpiled JS:

// U: Implicit input
// ö: generate a random number [0,U)
(U.ö())
  // g: run the result through a function
  .g(function(X, Y, Z) {
    // increment the result and compare to input
    return U === (++X)
      // if they are the same, roll again and add to current roll
      ? (X + rp())
      // if they are different, use current roll
      : X
   })

1
การใช้งานที่ดีมากN.g(f):)
Shaggy

เอาตัวแทงตัวเองและลงเอยด้วย 12 ไบต์ แต่ฉันไม่ต้องการโพสต์เพราะฉันชอบทางออกของคุณมากเกินไป!
ปุย

โพสต์เป็นคำตอบที่ต่างออกไป :)
dana

มันอาจจะสั้นกว่า แต่มันก็เป็นนรกที่น่าเกลียด
Shaggy

ฉันเห็น - Uใช่ผมพยายามที่จะเกิดขึ้นกับทางที่ไม่ก่อให้เกิดมลพิษ การข้ามเส้นดูเหมือนจะทำงานได้ดี นั่นเป็นเคล็ดลับที่ดี :)
dana

3

Japt , 12 ไบต์

มันอาจจะสั้นกว่าสารละลายของดาน่า แต่มันช่างน่ากลัวจริงๆ ฉันโพสต์เพียงเพราะดูเหมือนว่าตลอดไปเนื่องจากเรามีโซลูชัน Japtor ที่เริ่มต้นด้วยบรรทัดว่างเปล่า


ö
>°V©VªV+ß

ลองมัน


2

PowerShellขนาด 49 ไบต์

for($a=$l="$args";$a-eq$l){$o+=$l=1..$a|Random}$o

ลองออนไลน์!

วิธีการทำซ้ำ ชุดป้อนข้อมูล$argsไป$aและ$lม้วน AST (ทำเพื่อให้เราใส่ห่วงอย่างน้อยหนึ่งครั้ง) จากนั้นตราบใดที่ม้วนสุดท้ายเป็น-equal ไปยังอินพุตเราจะหมุนต่อไป ภายในวงที่เราสะสมไว้$oในม้วนสุดท้ายซึ่งมีการปรับปรุงโดยการสร้างช่วงจาก1การป้อนข้อมูล$aและเลือกRandomองค์ประกอบดังกล่าว (สุจริตฉันประหลาดใจเล็กน้อยที่$o+=$l=ทำงาน)เมื่อเราออกจากวงเราออก$oไปป์ไลน์และเอาท์พุทเป็นนัย


2

Forth (gforth) , 72 ไบต์

include random.fs
: f >r 0 begin i random 1+ >r i + r> i < until rdrop ;

ลองออนไลน์!

รหัสคำอธิบาย

include random.fs      \ include library file for random
: f                    \ start a new word definition
  >r                   \ stick the input on the return stack (for easy access)
  0                    \ add a counter to hold the sum
  begin                \ start an indefinite loop
    i random 1+        \ generate a random number from 1 to n
    >r i + r>          \ add the result to the counter, use the return stack to save a few bytes
    i <                \ check if result was less than n
  until                \ end the loop if it was, otherwise go back to begin
  rdrop                \ remove n from the return stack
;                      \ end the word definition

2

รุ่นที่ 70 ไบต์

@set t=0
:g
@set/at+=d=%random%%%%1+1
@if %d%==%1 goto g
@echo %t%

จะเข้าเป็นพารามิเตอร์บรรทัดคำสั่งn เป็นม้วนปัจจุบัน, ยอดรวมสะสม เพียงแค่ช่วยให้กลิ้งจนไม่เท่ากับ%1dtdn


2

เยลลี่ขนาด 9 ไบต์

x⁹X€Ä%ƇµḢ

ลองออนไลน์!

ลิงก์ monadic ที่รับ n เป็นอาร์กิวเมนต์และส่งคืนหมายเลขที่สร้างโดยตัวกระจาย n-sided die สิ่งนี้จะสร้างตัวเลข 256 จาก 1 ถึง n และส่งกลับผลรวมสะสมแรกที่ไม่ใช่จำนวนเต็มของ n ในทางทฤษฎีสิ่งนี้สามารถคืน 256n แต่สำหรับการตายแบบสองด้านนี้จะเกิดขึ้นเพียงคนเดียวทุกคน2256 ครั้ง

ทางเลือกที่ไม่มีข้อ จำกัด นี้คือ:

เยลลี่ 10 ไบต์

X³X¤+¥³ḍ¥¿

ลองออนไลน์!

หมายเหตุทั้งลิงค์ TIO สร้าง 400 หมายเลขเพื่อแสดงการกระจาย


2

Python 3 , 81 72 ไบต์

from random import*
def f(x,a=0):
 while a%x<1:a+=randint(1,x)
 return a

ลองออนไลน์!

-9 ไบต์ขอบคุณ ArBo

คำอธิบาย

import random             #load the random module              
def explodeDice(num):     #main function
    ans = 0                     #set answer to 0
    while a % num != 0:         #while a isn't a multiple of the input
        ans += random.randint(1, num) #add the next dice roll to answer
    return ans                  #return the answer

คุณสามารถบันทึก 1 ไบต์โดยใช้from random import*แทน
orthoplex

1
คุณสามารถได้รับการลงนี้ถึง 74 ไบต์ใช้นี้แก้ปัญหา recursive
คืนสิทธิ์ให้กับโมนิกา

1
@squid คุณสามารถบันทึก 1 ไบต์เช่นนี้
orthoplex

1
@orthoplex จากนั้นคุณสามารถย่อ if / else และทำให้เป็นหนึ่งซับได้ เริ่มดูเหมือนโซลูชันของฉันแล้ว)
ArBo

1
@ArBo ใช่แล้วนั่นเป็นเหตุผลที่ฉันไม่ได้เปลี่ยนเป็น recursive ไม่ต้องการคัดลอกคุณ
อาร์ทิมิสสนับสนุนโมนิก้า

2

TI-BASIC, 28 23 ไบต์

-5 ไบต์ขอบคุณที่โพสต์เมตานี้ !

Ans→N:0:Repeat fPart(Ans/N:Ans+randInt(1,N:End:Ans

Ansการป้อนข้อมูลที่อยู่ใน
เอาต์พุตอยู่ในAnsและพิมพ์ออกมาโดยปริยาย

ตัวอย่าง:

4
              4
prgmCDGF11
              5
6
              6
prgmCDGF11
              3

คำอธิบาย:

Ans→N:0:Repeat fPart(Ans/N:Ans+randInt(1,N:End:Ans   ;full logic

Ans→N                                                ;store the input in "N"
      0                                              ;leave 0 in "Ans"
        Repeat fPart(Ans/N                 End       ;loop until the sum
                                                     ; is not a multiple of
                                                     ; the input
                               randInt(1,N           ;generate a random
                                                     ; integer in [1,N]
                           Ans+                      ;then add it to "Ans"
                                               Ans   ;leave the sum in "Ans"
                                                     ;implicitly print "Ans"

หมายเหตุ:

  • TI-BASIC เป็นภาษาโทเค็น จำนวนตัวอักษรไม่เท่ากับจำนวนไบต์

เนื่องจากstartTmrไม่จำเป็นอีกต่อไปการส่งนี้จะใช้งานได้กับรุ่นของ TI-BASIC ก่อนหน้า TI-84 +
Tau

2

SmileBASIC 3, 49 ไบต์

ฟังก์ชั่นD N OUT Rใช้การกระจายลูกเต๋าหมุนวนซ้ำ

DEF D N OUT R
R=RND(N)+1IF R==N THEN R=R+D(N)
END

Ungolfed

DEF D N OUT R  'N is sides and R is output param (shorter than using RETURN in this case)
 R=RND(N)+1  'random number in [1, N]
 IF R==N THEN R=R+D(N)  'if roll is same as N then roll again and add
END

โปรดทราบว่าใน SmileBASIC ฟังก์ชั่นสามารถมีค่าส่งคืนได้หลายค่า หากฟังก์ชั่นมีหนึ่งค่าตอบแทนแล้วfun in OUT varและvar = fun(in)เหมือนกันซึ่งเป็นเหตุผลที่เราสามารถกำหนดฟังก์ชั่นในOUTรูปแบบและยังเรียกมันว่าในการแสดงออกในการทำงานของร่างกายตัวเอง ถ้าฉันได้กำหนดฟังก์ชั่นตามที่DEF D(N)ฉันจะต้องระบุอย่างชัดเจนRETURN Rในร่างกายของฟังก์ชั่น; การผสมทั้งไวยากรณ์ช่วยฉันไบต์



2

เยลลี่ขนาด 7 ไบต์

X=п⁸S_

ลิงก์ monadic ยอมรับจำนวนเต็มnซึ่งให้ผลเป็นจำนวนเต็ม

ลองออนไลน์! หรือดูจำนวนของ105 วิ่ง

อย่างไร?

X=п⁸S_ - Link: integer, n
  п    - Collect up while...
 =  ⁸   - ...condition: equal to chain's left argument, n
X       - ...next value: random number in [1..n]
     S  - sum
      _ - subtract n (since the collection starts with [n])

2

SmileBASIC ขนาด 41 ไบต์

INPUT N@L
S=S+RND(N)+1ON S MOD N GOTO@L?S

ก่อนอ่าน:

โปรดทราบว่าคุณไม่ควรส่งออกทวีคูณใด ๆ ของ n เนื่องจากจะระเบิดเสมอ

ฉันตระหนักว่ามากกว่าการตรวจสอบถ้าม้วนลูกเต๋าเป็นคุณก็สามารถทำซ้ำในขณะที่รวมเป็นหลายnn


2

AnyDiceขนาด 36 ไบต์

เกือบเป็นภาษาในตัว:

function:f I:n{result: [explode dI]}

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

set "explode depth" to 99

จะเพิ่มอีก 25 ไบต์ และจะไม่ตรงกับความต้องการจริง ๆ เพราะเป็นไปได้ในทางทฤษฎีสำหรับลูกเต๋าที่จะระเบิดได้มากกว่า 99 ครั้ง

เอาท์พุทของฟังก์ชั่นคือตายคือ ชนิดของบิวด์อิน AnyDice ที่เป็นผลลัพธ์และความน่าจะเป็นของผลลัพธ์


1
ฉันคิดว่าฉันโอเคกับมันไม่ระเบิดมาก 36 byte one ก็ดีสำหรับฉัน ฉันไม่ได้บอกว่าไม่มี buildins และฉันก็โอเคกับการมีที่นี่เพราะมันไม่เหมือนกับคำตอบ 1 หรือ 0 ไบต์ของคุณที่ชนะ แต่ยินดีต้อนรับสู่เว็บไซต์!
Rɪᴋᴇʀ

2

CJam , 19 ไบต์

qi{__mr)_T+:T;=}g;T

คำอธิบาย:

T is pre-set to 0

qi{__mr)_T+:T;=}g;T - whole code
qi                  - read input as integer (n) | Stack: n
  {            }    - block
   __               - Duplicate twice | Stack: n n n
     mr)            - Choose a random number from 1 to n (r). Since 'mr' picks a
                      number from 0 to n-1, the number has to be incremented with ')' 
                      Stack: n n r
        _           - Duplicate |  Stack: n n r r
         T          - push T | Stack: n n r r T
          +         - add the random number to T (t) | Stack: n n r t
           :T;      - pop the value and store in T | Stack: n n r
              =     - are the top two stack values the same (c) | Stack: n c
               }
                g   - do while loop that pops the condition from the stack after each
                      iteration | Stack: n
                 ;  - pop the top stack element and discard | Stack: T
                  T - push T | Stack: T
                    - implicit output

หรือใน pseudocode:

input n
var sum = 0
do {
    var random_number = pick random number from 1 to n
    sum = sum + random_number
} while (random_number == n)
output n

ในฐานะผังงาน:

ผังของรหัส

ลองออนไลน์!


2

Excel VBA ขนาด 46 ไบต์

ขอบคุณ @TaylorScott

Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t

ดำเนินการในหน้าต่างคำสั่ง

เป็นฟังก์ชั่นที่ผู้ใช้กำหนด

Excel VBA, 108 67 ไบต์

Function z(i)
Do
v=Int((i*Rnd)+1)
z=z+v
Loop While v=i
End Function

คุณสามารถลดขนาดลงได้เล็กน้อยโดยใช้do.. loop whileลูปและแปลงฟังก์ชันเป็นฟังก์ชันหน้าต่างทันที - Do:v=-Int(-[A1]*Rnd):t=t+v:Loop While[A1]=v:?t- 46 Bytes
Taylor Scott

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