多个骰子辊的频率分布


23

给定两个正整数ab,输出滚动a侧ba时间并累加结果的频率分布。

如果掷骰子的每个可能序列出现一次,则频率分布会列出每个可能总和的频率。因此,频率是其和等于的整数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吗?(或者,如果不是,那么一个单面骰子的总和的频率列表应该是什么样的?)
Misha Lavrov

我们可以有前导零还是尾随零?
xnor

Answers:


9

八度,38字节

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

在线尝试!

说明

添加独立随机变量对应于卷积其概率质量函数(PMF)或乘以其特征函数(CF)。因此,a独立的,均匀分布的变量之和的CF 由提高到的幂的单个变量的CF 给出a

CF本质上是PMF的傅立叶变换,因此可以通过FFT计算。单一的PMF b-sided模具是一致的12,..., b。但是,需要进行两个修改:

  • 1代替实际概率值(1/b)。这样,结果将被归一化,并根据需要包含整数。
  • 需要使用零填充,以便FFT输出具有适当的大小(a*b-a+1),并且FFT假定的隐式周期性行为不会影响结果。

一旦获得了总和的特征函数,就可以使用逆FFT来计算最终结果,并应用舍入来校正浮点误差。

考虑输入a=2b=6。该代码a:a*b<a+b构建了一个带有b=6一个零填充到size 的向量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]

在这里几乎可以识别正弦函数(矩形脉冲的傅立叶变换)。

(...).^a将每个条目提高到a然后ifft(...)进行逆FFT,

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

尽管这种情况下的结果恰好是整数,但是通常可能存在的相对误差1e-16,这就是为什么round(...)需要这样做。


1
我真的很感动!
rahnema17年

@ rahnema1信号处理获胜!
路易斯·门多

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)是单个模具辊的生成函数,并且产品对应于卷积-将骰子的值相加-结果给出了频率分布。


6

Haskell90 79 77 75字节

感谢Lynn的笛卡尔乘积技巧。-11字节要归功于Funky Computer Man的许多Haskell技巧,命名要归功于-2字节,感谢Laikoni要得负-2字节。欢迎打高尔夫球!在线尝试!

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

不打高尔夫球

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

测试套件


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的Octave解的一个端口,fft(z, inverse=T)不幸地返回了未归一化的逆FFT,因此我们必须除以长度,然后返回一个complex向量,因此只取实数部分。


发挥出色-昨天的cmdscaleI数字回报:-)
flodel

@flodel哈!我实际上是要奖励您一笔赏金:)
Giuseppe

你不是在开玩笑!你们真慷慨!我很高兴看到您的答案(并从中学习),我会尽快归还!
flodel

3

SageMath,40个字节

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

在线尝试

convolution计算两个列表的离散卷积。reduce它在锡上说了什么。[1]*bb 1s 的列表,的频率分布1db[[1]*b]*a制作的a副本的嵌套列表b 1


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€-完整程序(双向)| 示例: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字节。


嗯...这只需要一个输入
Herman L

@HermanLauenstein抱歉,我完全忽略了问题的一部分...很快就会解决。
尼尔

1

J25 24 21 20字节

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

在线尝试!

最初,我增加了[0..n-1]列表以获得[1..n],但显然没有必要。


好答案。这是相同数量字节的默认版本:#/.~@,@(+///)@$i.@{:。似乎应该有一种方法可以将其简化为动词二进位,但我却做不到。
约拿(Jonah)

@Jonah,您可以参加额外/活动+//
FrownyFrog

其实你是对的。它恰好可以双向工作。我猜该解决方案会节省一个字节:)
约拿(Jonah)

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个字节感谢Xcoder先生。在线尝试!

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

不打高尔夫球

                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

您不需要@,对吗?
Xcoder先生17年

作为旁注,我找到了一个有趣的替代方案:R∙♂Σ╗╜╔⌠╜c⌡M
Xcoder先生,2017年

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与环境相关,您知道
Leaky 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个字节。
凯文·克鲁伊森

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.