[OT] Generating distribution of N dice rolls
Timon Gehr
timon.gehr at gmx.ch
Thu Nov 10 10:45:50 UTC 2022
On 10.11.22 03:10, H. S. Teoh wrote:
> This is technically OT, but I thought I'd pick the smart brains here for
> my project, which happens to be written in D. ;-)
>
> Basically, I want to write a function that takes 2 uint arguments k and
> N, and simulates rolling N k-sided dice and counting how many 1's, 2's,
> 3's, ... k's were rolled. Something like this:
>
> uint[k] diceDistrib(uint k)(uint N)
> in(k > 0)
> in(N > 0)
> out(r; r[].sum == N)
> {
> uint[k] result;
> foreach (i; 0 .. N) {
> result[uniform(0, k)]++;
> }
> return result;
> }
>
> The above code works and does what I want, but since N may be large, I'd
> like to refactor the code to loop over k instead of N. I.e., instead of
> actually rolling N dice and tallying the results, the function would
> generate the elements of the output array directly, such that the
> distribution of the array elements follow the same probabilities as the
> above code.
>
> Note that in all cases, the output array must sum to N; it is not enough
> to merely simulate the roll distribution probabilistically.
>
> Any ideas? (Or links if this is a well-studied problem with a known
> solution.)
> ...
The distribution of the output is multinomial(n,k,[1/k,1/k,...,1/k]),
i.e., n trials, k events, and the events follow an uniform distribution.
https://en.wikipedia.org/wiki/Multinomial_distribution
It is at least as hard to sample as binomial(n,1/k), because that is the
marginal distribution of each component of the result.
I guess one approach is this (if you can find a way to sample from
binomial distributions that is good enough for your use case):
auto tot=n;
foreach(i;0..k){
result[i]=binomial(tot,1.0/(k-i));
tot-=result[i];
}
return result;
This samples the result one component at a time.
> <ObDReference> I love how D's new contract syntax makes it so conducive
> to expressing programming problem requirements. ;-) </ObDReference>
>
:)
More information about the Digitalmars-d
mailing list