การแจกแจงความถี่ของการทอยลูกเต๋าหลายลูก


23

ได้รับสองจำนวนเต็มบวกaและbการส่งออกการกระจายความถี่ของการกลิ้งbตายด้านเดียวaครั้งและสรุปผล

การแจกแจงความถี่แสดงรายการความถี่ของผลรวมแต่ละค่าที่เป็นไปได้หากแต่ละลำดับลูกเต๋าที่เป็นไปได้เกิดขึ้นหนึ่งครั้ง b**aดังนั้นความถี่เป็นจำนวนเต็มซึ่งเท่ากับผลรวม

กฎระเบียบ

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

กรณีทดสอบ

รูปแบบ: a b: output

1 6: [1, 1, 1, 1, 1, 1]
2 6: [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
3 6: [1, 3, 6, 10, 15, 21, 25, 27, 27, 25, 21, 15, 10, 6, 3, 1]
5 2: [1, 5, 10, 10, 5, 1]
6 4: [1, 6, 21, 56, 120, 216, 336, 456, 546, 580, 546, 456, 336, 216, 120, 56, 21, 6, 1]
10 10: [1, 10, 55, 220, 715, 2002, 5005, 11440, 24310, 48620, 92368, 167860, 293380, 495220, 810040, 1287484, 1992925, 3010150, 4443725, 6420700, 9091270, 12628000, 17223250, 23084500, 30427375, 39466306, 50402935, 63412580, 78629320, 96130540, 115921972, 137924380, 161963065, 187761310, 214938745, 243015388, 271421810, 299515480, 326602870, 351966340, 374894389, 394713550, 410820025, 422709100, 430000450, 432457640, 430000450, 422709100, 410820025, 394713550, 374894389, 351966340, 326602870, 299515480, 271421810, 243015388, 214938745, 187761310, 161963065, 137924380, 115921972, 96130540, 78629320, 63412580, 50402935, 39466306, 30427375, 23084500, 17223250, 12628000, 9091270, 6420700, 4443725, 3010150, 1992925, 1287484, 810040, 495220, 293380, 167860, 92368, 48620, 24310, 11440, 5005, 2002, 715, 220, 55, 10, 1]
5 50: [1, 5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855, 10626, 12650, 14950, 17550, 20475, 23751, 27405, 31465, 35960, 40920, 46376, 52360, 58905, 66045, 73815, 82251, 91390, 101270, 111930, 123410, 135751, 148995, 163185, 178365, 194580, 211876, 230300, 249900, 270725, 292825, 316246, 341030, 367215, 394835, 423920, 454496, 486585, 520205, 555370, 592090, 630371, 670215, 711620, 754580, 799085, 845121, 892670, 941710, 992215, 1044155, 1097496, 1152200, 1208225, 1265525, 1324050, 1383746, 1444555, 1506415, 1569260, 1633020, 1697621, 1762985, 1829030, 1895670, 1962815, 2030371, 2098240, 2166320, 2234505, 2302685, 2370746, 2438570, 2506035, 2573015, 2639380, 2704996, 2769725, 2833425, 2895950, 2957150, 3016881, 3075005, 3131390, 3185910, 3238445, 3288881, 3337110, 3383030, 3426545, 3467565, 3506006, 3541790, 3574845, 3605105, 3632510, 3657006, 3678545, 3697085, 3712590, 3725030, 3734381, 3740625, 3743750, 3743750, 3740625, 3734381, 3725030, 3712590, 3697085, 3678545, 3657006, 3632510, 3605105, 3574845, 3541790, 3506006, 3467565, 3426545, 3383030, 3337110, 3288881, 3238445, 3185910, 3131390, 3075005, 3016881, 2957150, 2895950, 2833425, 2769725, 2704996, 2639380, 2573015, 2506035, 2438570, 2370746, 2302685, 2234505, 2166320, 2098240, 2030371, 1962815, 1895670, 1829030, 1762985, 1697621, 1633020, 1569260, 1506415, 1444555, 1383746, 1324050, 1265525, 1208225, 1152200, 1097496, 1044155, 992215, 941710, 892670, 845121, 799085, 754580, 711620, 670215, 630371, 592090, 555370, 520205, 486585, 454496, 423920, 394835, 367215, 341030, 316246, 292825, 270725, 249900, 230300, 211876, 194580, 178365, 163185, 148995, 135751, 123410, 111930, 101270, 91390, 82251, 73815, 66045, 58905, 52360, 46376, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985, 4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70, 35, 15, 5, 1]

เราสามารถสันนิษฐานได้ว่าbอย่างน้อย 2 หรือไม่? (หรือไม่ถ้าไม่รายการความถี่สำหรับผลบวกของการตายแบบ 1 ด้านเป็นอย่างไร)
Misha Lavrov

เราขอมีเลขศูนย์นำหน้าหรือต่อท้ายได้ไหม
xnor

คำตอบ:


9

อ็อกเทฟ 38 ไบต์

@(a,b)round(ifft(fft((a:a*b<a+b)).^a))

ลองออนไลน์!

คำอธิบาย

การเพิ่มตัวแปรสุ่มแบบอิสระสอดคล้องกับการทำให้ฟังก์ชั่นความน่าจะเป็นมวล (PMF) หรือการคูณฟังก์ชั่นคุณลักษณะ (CF) ดังนั้น CF ของผลรวมของการเป็นอิสระตัวแปรกระจายเหมือนกันจะได้รับโดยที่ตัวแปรเดียวยกกำลังของaa

CF คือการแปลงฟูริเยร์ของ PMF และสามารถคำนวณได้ผ่านทาง FFT PMF ของเดียวbตายด้านเดียวคือเครื่องแบบ1, 2, ... b, อย่างไรก็ตามจำเป็นต้องมีการแก้ไขสองอย่าง:

  • 1ถูกใช้แทนค่าความน่าจะเป็นจริง ( 1/b) วิธีนี้ผลลัพธ์จะถูกทำให้เป็นมาตรฐานและจะมีจำนวนเต็มตามที่ต้องการ
  • ต้องใช้การเสริมด้วยศูนย์เพื่อให้เอาท์พุท FFT มีขนาดที่เหมาะสม ( a*b-a+1) และพฤติกรรมตามระยะเวลาที่สันนิษฐานโดย FFT จะไม่ส่งผลต่อผลลัพธ์

เมื่อได้รับฟังก์ชั่นคุณลักษณะของผลรวมแล้วอินเวอร์ส FFT จะถูกใช้เพื่อคำนวณผลลัพธ์สุดท้ายและการปัดเศษจะถูกนำไปใช้เพื่อแก้ไขความไม่ถูกต้องของจุดลอย

ตัวอย่าง

พิจารณาอินพุตa=2, b=6. รหัสa:a*b<a+bจะสร้างเวกเตอร์ด้วยb=6วัตถุโดยไม่มีขนาดเท่ากับขนาดของแผ่นa*b-a+1:

[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

จากนั้นfft(...)ให้

[36, -11.8-3.48i, 0.228+0.147i, -0.949-1.09i, 0.147+0.321i, -0.083-0.577i, -0.083+0.577i, 0.147-0.321i, -0.949+1.09i, 0.228-0.147i, -11.8+3.48i]

เราสามารถจดจำฟังก์ชัน sinc ได้ที่นี่ (การแปลงฟูริเยร์ของพัลส์รูปสี่เหลี่ยมผืนผ้า)

(...).^aยกแต่ละรายการไปaแล้วifft(...)เตะ FFT ผกผันซึ่งจะช่วยให้

[1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]

แม้ว่าผลลัพธ์ในกรณีนี้จะเป็นจำนวนเต็ม แต่โดยทั่วไปอาจมีข้อผิดพลาดสัมพัทธ์ของลำดับ1e-16ซึ่งเป็นสาเหตุที่round(...)จำเป็น


1
ฉันประทับใจจริงๆ!
rahnema1

@ rahnema1 การประมวลสัญญาณสำหรับผู้ชนะ!
Luis Mendo

8

Mathematica, 29 ไบต์

Tally[Tr/@Range@#2~Tuples~#]&

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

Mathematica, 38 ไบต์

CoefficientList[((x^#2-1)/(x-1))^#,x]&

ขยายและใช้ค่าสัมประสิทธิ์ของ(1+x+x^2+...+x^(a-1))^b xเนื่องจาก1+x+x^2+...+x^(a-1)เป็นฟังก์ชั่นการสร้างสำหรับผลิตภัณฑ์แผ่นเดียวและผลิตภัณฑ์ที่สอดคล้องกับ convolutions - การเพิ่มคุณค่าของลูกเต๋า - ผลลัพธ์จะให้การแจกแจงความถี่


6

Haskell , 90 79 77 75 ไบต์

ขอขอบคุณที่ลินน์สำหรับเคล็ดลับผลิตภัณฑ์ Cartesian -11 ไบต์ขอบคุณเทคนิค Haskell มากมายจาก Funky Computer Man, -2 ไบต์จากการตั้งชื่อ, -2 ไบต์ขอบคุณ Laikoni ยินดีต้อนรับคำแนะนำการเล่นกอล์ฟ! ลองออนไลน์!

import Data.List
g x=[1..x]
a!b=map length$group$sort$map sum$mapM g$b<$g a

Ungolfed

import Data.List
rangeX x = [1..x]
-- sums of all the rolls of b a-sided dice
diceRolls a b = [sum y | y <- mapM rangeX $ fmap (const b) [1..a]]
-- our dice distribution
distrib a b = [length x | x <- group(sort(diceRolls a b))]

ใช้$แทน()การบันทึก 2 ไบต์ TIO
Wheat Wizard




(map length$)=(length<$>)สำหรับสองไบต์
Michael Klein

4

Pyth - 10 ไบต์

เพียงแค่ใช้เวลารวมกันลูกเต๋าเป็นไปได้ทั้งหมดโดยการใช้ผลิตภัณฑ์คาร์ทีเซียนของ[1, b], aครั้งข้อสรุปและได้รับความยาวของแต่ละกลุ่มทุน

lM.gksM^SE

Test Suite


4

05AB1E , 8 ไบต์

LIãO{γ€g

ลองออนไลน์!

อย่างไร?

LIãO {γ€ g - โปรแกรมเต็มรูปแบบ

L - ช่วง [1 ... อินพุต # 1]
 I - อินพุต # 2
  ã - พลังคาร์ทีเซียน
   O - แผนที่พร้อมผลรวม
    {- จัดเรียง
     γ - องค์ประกอบที่เท่ากันติดต่อกันเป็นกลุ่ม
      € g - รับความยาวของแต่ละ


4

R , 52 ไบต์

function(a,b)Re(fft(fft(a:(a*b)<a+b)^a,T)/(a*b-a+1))

ลองออนไลน์!

พอร์ตของการแก้ปัญหาคู่ @Luis Mendo ของ , fft(z, inverse=T)โชคร้ายกลับ FFT ผกผัน unnormalized ดังนั้นเราจึงต้องหารด้วยระยะเวลาและผลตอบแทนcomplexเวกเตอร์เพื่อให้เราใช้เวลาเพียงส่วนจริง


เล่นได้ดี - คืนทุนสำหรับเมื่อวานนี้cmdscaleฉันคิดว่า :-)
flodel

@flodel hah! จริง ๆ แล้วฉันจะมอบรางวัลให้คุณหนึ่งรางวัลสำหรับสิ่งนั้น :)
Giuseppe

คุณไม่ได้ล้อเล่น! คุณใจดีมาก! ฉันสนุกกับการเห็น (และเรียนรู้จาก) คำตอบของคุณฉันจะจ่ายคืนให้อย่างรวดเร็ว!
flodel

3

SageMath, 40 ไบต์

lambda a,b:reduce(convolution,[[1]*b]*a)

ลองออนไลน์

convolutionคำนวณการแยกแบบไม่ต่อเนื่องของสองรายการ reduceทำในสิ่งที่พูดบนกระป๋อง [1]*bเป็นรายการของb 1s 1dbการกระจายความถี่ของ [[1]*b]*aทำรายการซ้อนaของb 1s


Python 2 + NumPy , 56 ไบต์

lambda a,b:reduce(numpy.convolve,[[1]*b]*a)
import numpy

ลองออนไลน์!

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

numpy.ones((a,b))เป็นวิธีที่ "ถูกต้อง" ในการสร้างอาร์เรย์สำหรับใช้กับ NumPy และสามารถใช้แทนได้[[1]*b]*aแต่น่าเสียดายที่นานกว่านั้น


3

เยลลี่ 5 ไบต์

ṗS€ĠẈ

ลองออนไลน์!

โปรดทราบว่านี่ใช้อาร์กิวเมนต์ในลำดับย้อนกลับ

อย่างไร?

ṗS€ĠL€ - โปรแกรมเต็มรูปแบบ (dyadic) | ตัวอย่าง: 6, 2

ṗ - พลังคาร์ทีเซียน (พร้อมช่วงโดยนัย) | [[1, 1], [1, 2], ... , [6, 6]]
 S € - รวมกัน | [2, 3, 4, ... , 12]
   Ġ - ดัชนีกลุ่มตามค่า | [[1], [2, 7], [3, 8, 13], ... , [36]]
    L € - ความยาวของแต่ละกลุ่ม | [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]

ทางเลือกอื่น ๆ :

ṗZSĠL€
ṗZSµLƙ
ṗS€µLƙ






1

JavaScript (ES6), 94 ไบต์

f=(n,m,a=[1],b=[])=>n?[...Array(m)].map((_,i)=>a.map((e,j)=>b[j+=i]=(b[j]|0)+e))&&f(n-1,m,b):a
<div oninput=o.textContent=f(+n.value,+m.value).join`\n`><input id=n type=number min=0 value=0><input id=m type=number min=1 value=1><pre id=o>1

ถูก จำกัด ด้วยการล้นจำนวนเต็มแบบ 32 บิต แต่สามารถใช้การลอยแทนค่า 1 ไบต์


อืมม ... นี่ใช้เพียงหนึ่งอินพุต
เฮอร์แมน L

@HermanLauenstein ขออภัยฉันมองข้ามส่วนหนึ่งของคำถามนั้นไป ... จะแก้ไขในไม่ช้า
Neil

1

J , 25 24 21 20 ไบต์

3 :'#/.~,+//y$i.{:y'

ลองออนไลน์!

ตอนแรกฉันเพิ่มรายการ [0..n-1] เพื่อรับ [1..n] แต่ดูเหมือนไม่จำเป็น


คำตอบที่ดี #/.~@,@(+///)@$i.@{:นี่เป็นรุ่นโดยปริยายสำหรับหมายเลขเดียวกันของไบต์: ดูเหมือนว่ามันควรจะมีวิธีที่จะทำให้มันลดลงไปอีกเล็กน้อยทำให้การสร้างคำกริยาเป็นคำกริยา แต่ฉันก็ไม่สามารถทำได้
โยนาห์

@Jonah คุณมีความพิเศษ/ใน+//
FrownyFrog

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

1

Javascript (ES6), 89 ไบต์

b=>g=a=>a?(l=[..."0".repeat(b-1),...g(a-1)]).map((_,i)=>eval(l.slice(i,i+b).join`+`)):[1]

รับอินพุตในรูปแบบ currying ในลำดับย้อนกลับ f(b)(a)

f=b=>g=a=>a>0?(l=[..."0".repeat(b-1),...g(a-1)]).map((_,i)=>eval(l.slice(i,i+b).join`+`)):[1]
r=_=>{o.innerText=f(+inb.value)(+ina.value)}
<input id=ina type=number min=0 onchange="r()" value=0>
<input id=inb type=number min=1 onchange="r()" value=1>
<pre id=o></pre>


1

อันที่จริง , 13 12 ไบต์

-1 ไบต์ขอบคุณ Mr. Xcoder ลองออนไลน์!

R∙♂Σ;╗╔⌠╜c⌡M

Ungolfed

                Implicit input: b, a
R∙              ath Cartesian power of [1..b]
  ♂Σ            Get all the sums of the rolls, call them dice_rolls
    ;╗          Duplicate dice_rolls and save to register 0
      ╔         Push uniquify(dice_rolls)
       ⌠  ⌡M    Map over uniquify(dice_rolls), call the variable i
        ╜         Push dice_rolls from register 0
         c        dice_rolls.count(i)
                Implict return

คุณไม่ต้องการ@คุณใช่ไหม
Mr. Xcoder

จากบันทึกด้านข้างฉันพบทางเลือกที่น่าสนใจ:R∙♂Σ╗╜╔⌠╜c⌡M
Mr. Xcoder

1

AWK , 191 ไบต์

ส่งออกความถี่เป็นคอลัมน์แนวตั้ง

func p(z){for(m in z)S[z[m]]++
for(i=$1;i<=$1*$2;i++)print S[i]}func t(a,b,z,s){if(a){if(R++)for(n in z)for(i=0;i++<b;)s[n,i]=z[n]+i
else for(i=0;i++<b;)s[i]=i
t(--a,b,s)}else p(z)}{t($1,$2)}

ลองออนไลน์!

การเพิ่ม 6 ไบต์เพิ่มเติมอนุญาตให้มีอินพุตหลายชุด

func p(z,S){for(m in z)S[z[m]]++
for(i=$1;i<=$1*$2;i++)print S[i]}func t(a,b,z,s){if(a){if(R++)for(n in z)for(i=0;i++<b;)s[n,i]=z[n]+i
else for(i=0;i++<b;)s[i]=i
t(--a,b,s)}else p(z)}{R=0;t($1,$2)}

ลองออนไลน์!


1

Clojure, 86 ไบต์

#(sort-by key(frequencies(reduce(fn[r i](for[y(range %2)x r](+ x y 1)))[0](range %))))

ตัวอย่าง:

(def f #(...))
(f 5 4)

([5 1] [6 5] [7 15] [8 35] [9 65] [10 101] [11 135] [12 155] [13 155] [14 135] [15 101] [16 65] [17 35] [18 15] [19 5] [20 1])

0

C (gcc) , 142 ไบต์

i,j,k;int*f(a,b){int*r=malloc(sizeof(int)*(1+a*~-b));r[0]=1;for(i=1;i<=a;i++)for(j=i*~-b;j>=0;j--)for(k=1;k<b&k<=j;k++)r[j]+=r[j-k];return r;}

ลองออนไลน์!


sizeof(int)? จริงๆ?
orlp

@orlp ขึ้นอยู่กับสภาพแวดล้อมคุณรู้
Nun

2
มันอนุญาตให้โปรแกรม C สมมติสถาปัตยกรรมเฉพาะ ตราบใดที่มันทำงานบนเครื่องอย่างน้อยหนึ่งเครื่อง นอกจากนี้ยัง8สามารถทำงานกับสถาปัตยกรรมใด ๆ โดยรวมได้เล็กน้อย แต่ก็โอเค
orlp

r[0]=1;for(i=1;i<=a;i++)for(j=i*~-b;-> for(i=r[0]=1;i<=a;)for(j=i++*~-b;สำหรับ -2 ไบต์
Kevin Cruijssen

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