| Bytes | Lang | Time | Link |
|---|---|---|---|
| 012 | 05AB1E legacy | 171210T210451Z | Mr. Xcod |
| 006 | Vyxal | 241010T022810Z | emanresu |
| 035 | Pari/GP | 171211T055215Z | alephalp |
| 046 | SageMath | 171213T053044Z | user4594 |
| 094 | Perl 5 | 171211T174309Z | Xcali |
| 051 | R | 171211T003844Z | Giuseppe |
| 096 | Clojure | 171211T142229Z | NikoNyrh |
| 044 | Mathematica | 171210T221906Z | ZaMoC |
| 074 | JavaScript ES6 | 171211T113408Z | Arnauld |
| 072 | Ruby | 171211T042557Z | Reinstat |
| 083 | JavaScript ES6 | 171211T005226Z | Neil |
| nan | Clean | 171210T235724Z | Οurous |
| 007 | Husk | 171210T231037Z | Zgarb |
| 026 | Wolfram Language Mathematica | 171210T225628Z | Misha La |
| 064 | Haskell | 171210T200048Z | flawr |
| 056 | Octave | 171210T204252Z | flawr |
| 008 | MATL | 171210T221723Z | Luis Men |
| 119 | Python 2 | 171210T204927Z | Chas Bro |
| 010 | APL Dyalog Classic | 171210T205004Z | ngn |
| 054 | Haskell | 171210T212951Z | xnor |
| 014 | Jelly | 171210T202916Z | dylnan |
| 007 | Jelly | 171210T202959Z | Jonathan |
| 012 | Pyth | 171210T204305Z | Mr. Xcod |
05AB1E (legacy), 12 bytes
€L.«â€˜O{γ€g
How it works
€L.«âOO{γ€g - Full program.
€L - For each N in the list, get [1 .. N].
.« - Fold a dyadic function between each element in a list from right to left.
â - And choose cartesian product as that function.
O - Flatten each.
O - Sum each.
{γ - Sort, and group into runs of equal adjacent values.
€g - Get the lengths of each.
Saved 1 byte thanks to Emigna! Thanks Kevin for pointing out that actually doesn't work!
Vyxal, 6 bytes
ɾΠṠsĠ@
ɾ # Map each to range(1,n)
Π # Take the cartesian product
Ṡ # Sum each
s # Sort
@ # Get the lengths
Ġ # of groups of identical items
SageMath, 46 bytes
lambda*a:reduce(convolution,[x*[1]for x in a])
This is an adaptation of my solution to the other challenge. It takes in any number of dice as parameters (e.g. f(4,4,6,6,6) for 2d4+3d6), and returns a list.
Python 2 + NumPy, 62 bytes
lambda*a:reduce(numpy.convolve,[x*[1]for x in a])
import numpy
As before, I've included this solution with the above one, since they're essentially equivalent. Note that this function returns a NumPy array and not a Python list, so the output looks a bit different if you print it.
numpy.ones(x) is the "correct" way to make an array for use with NumPy, and thus it could be used in place of [x*[1]], but it's unfortunately much longer.
Perl 5, 94 bytes
map$k{$_}++,map eval,glob join'+',map'{'.(join',',1..$_).'}',<>;say$k{$_}for sort{$a-$b}keys%k
Input format is a list of dice separated by newlines. Thus, 1d10+2d8 would input as:
10
8
8
R, 51 bytes
function(D){for(x in D)F=outer(F,1:x,"+")
table(F)}
Takes a list of dice and returns a named vector of frequencies; the names (values of the dice sums) are printed above the frequencies.
R, 59 bytes
function(D)table(Reduce(function(x,y)outer(x,1:y,"+"),D,0))
A Reduce approach rather than the iterative one above.
R, 62 bytes
function(D)Re(convolve(!!1:D,"if"(sum(x<-D[-1]),f(x),1),,"o"))
A convolution approach. It will give a few warnings that it's only using the first element of D for the expression 1:D but it doesn't affect the output. If we didn't have to take the Real part of the solution, it'd be 58 bytes.
Clojure, 96 bytes
#(sort-by key(frequencies(reduce(fn[R D](for[d(range D)r R](+ r d 1)))[0](mapcat repeat % %2))))
First input is a list of number of dice, and the second input is a list of number of sides on each dice.
Mathematica, 44 bytes
Outputs the frequencies labeled with the corresponding sums
Tally@*Fold[Join@@Table[#+i,{i,#2}]&]@*Range
-5 bytes from Martin Ender
thanks to Misha Lavrov for letting me know that "labeled" is valid
JavaScript (ES6), 76 74 bytes
Takes input as a list of dice.
a=>(g=k=>a.map(d=>(s+=n%d|0,n/=d),s=0,n=k)|n?x:g(k+1,x[s]=-~x[s]))(0,x=[])
Test cases
Processing the last two test cases would require to enable TCO or increase the default stack size limit of the JS engine.
let f =
a=>(g=k=>a.map(d=>(s+=n%d|0,n/=d),s=0,n=k)|n?x:g(k+1,x[s]=-~x[s]))(0,x=[])
console.log(f([10,10]).join(', '))
console.log(f([1,9]).join(', '))
console.log(f([12,8]).join(', '))
console.log(f([4,4,6,6,6]).join(', '))
console.log(f([3,13,13]).join(', '))
Formatted and commented
NB: This is a commented version of my initial submission which was using reduce(). It's 2 bytes longer but easier to read.
a => // given the list of dice a
(g = k => // g = recursive function taking k = counter
a.reduce((k, d) => // for each die d in a:
( // k % d represents the current face of d
s += k % d, // we add it to the total s
k / d | 0 // and we update k to pick the face of the next die
), // initialization:
k, // start with the current value of k
s = 0 // total = 0
) ? // reduce() returns 1 as soon as k = product of all dice
x // in which case we're done: stop recursion and return x
: // else:
g( // do a recursive call to g() with:
k + 1, // k incremented
x[s] = -~x[s] // x[s] incremented
) // end of recursive call
)(0, x = []) // initial call to g() with k = 0 and x = empty array
Ruby, 72 bytes
->d{r=[0]*d.sum
[0].product(*d.map{|e|[*1..e]}){|e|r[e.sum-1]+=1}
r-[0]}
Takes a list of dice as input. No doubt it can be golfed down, but not too bad.
JavaScript (ES6), 83 bytes
f=(n,...a)=>n?f(...a).map((e,i)=>[...Array(n)].map(_=>r[i]=~~r[i++]+e),r=[])&&r:[1]
g=s=>o.textContent=f(...(s.match(/\d+/g)||[]).map(n=>+n)).join`, `
<input oninput=g(this.value)><p id=o>1
Takes input of each die as a separate parameter.
Clean, 154 142 136 107 100 85+13=98 bytes
Input is a list of dice.
\l#t=foldr(\a-> \b=[x+y\\x<-[1..a],y<-b])[0]l
=[length[v\\v<-t|u==v]\\u<-removeDup t]
Answer is in the form of a lambda.
+13 bytes from import StdEnv, which imports the module needed for this to work.
Husk, 7 bytes
mLkΣΠmḣ
Input is a list of dice. Try it online!
Explanation
mLkΣΠmḣ Implicit input, say x=[3,3,6].
mḣ Map range: [[1,2,3],[1,2,3],[1,2,3,4,5,6]]
Π Cartesian product: [[1,1,1],[1,1,2],..,[3,3,6]]
kΣ Classify by sum: [[[1,1,1]],[[1,1,2],[1,2,1],[2,1,1]],..,[[3,3,6]]]
mL Map length: [1,3,6,8,9,9,8,6,3,1]
Wolfram Language (Mathematica), 26 bytes
Tally[Tr/@Tuples@Range@#]&
A modification of my answer to the previous challenge. This just generates all possible outcomes, adds them up, and tallies the results.
For fun, we could write it as Tally@*Total@*Thread@*Tuples@*Range, but that's longer.
Wolfram Language (Mathematica), 41 bytes
CoefficientList[1##&@@((x^#-1)/(x-1)),x]&
This is the convolution-based approach (here, we take convolutions via the product of generating functions - 1+x+x^2+...+x^(N-1) is the generating function for rolling a dN - and then take the list of coefficients). I include it because the first solution isn't practical for large inputs.
Haskell, 80 78 64 bytes
This solution ended up being almost the same as the one of @Sherlock9 in the previous challenge with the maybe more natural approach. @xnor has an even shorter Haskell solution!
import Data.List
g x=[1..x]
map length.group.sort.map sum.mapM g
Explanation:
mapM g -- all possible outcomes
map sum -- the sums of all possible outcomes
map length.group.sort -- count the frequency of each sum
Previous solution:
This is using the @AndersKaseorg discrete convolution function. The observation here is that the distribution of e.g. a 3-sided and a 5-sided dice is the discrete convolution of the two vectors [1,1,1] and [1,1,1,1,1].
foldl1(#).map(`take`l)
(a:b)#c=zipWith(+)(0:b#c)$map(a*)c++[]#b
_#c=0<$c
l=1:l
Octave, 88 69 58 56 bytes
As mentioned in the Haskell answer, this uses the fact that the distribution of e.g. a 3-sided and a 5-sided dice is the discrete convolution of the two vectors [1,1,1] and [1,1,1,1,1]. Thanks @LuisMendo for -11 bytes worth of clever golfing!
function y=f(c);y=1:c;if d=c(2:end);y=conv(~~y,f(d));end
This submission is using an recursive approach. But if you would use a loop it would be slightly longer:
function y=f(c);y=1;for k=cellfun(@(x)ones(1,x),c,'Un',0);y=conv(y,k{1});end
MATL, 8 bytes
1i"@:gY+
The input is an array of (possibly repeated) die sizes.
Try it online! Or verify all test cases.
Explanation
1 % Push 1
i % Input: numeric array
" % For each k in that array
@ % Push k
: % Range: gives [1 2 ... k]
g % Convert to logical: gives [1 1 ... 1]
Y+ % Convolution, with full size
% End (implicit). Display (implicit)
Python 2, 120 119 bytes
lambda v:[reduce(lambda a,c:sum([[b+y for b in a]for y in range(c)],[]),v,[0]).count(d)for d in range(sum(v)-len(v)+1)]
Thks for Mego/Jonathon Allan for 1 byte.
APL (Dyalog Classic), 12 10 bytes
-2 thanks to @Adám
⊢∘≢⌸+/↑,⍳⎕
the input ⎕ is a list of N dice
⍳⍵ is an N-dimensional array of nested vectors - all possible die throws
+/↑, flattens the arrays and sums the throws
⊢∘≢⌸ counts how many of each unique sum, listed in order of their first appearance, which fortunately coincides with their increasing order
Haskell, 54 bytes
1%r=r
n%r=zipWith(+)(r++[0,0..])$0:(n-1)%r
foldr(%)[1]
Haskell, 63 bytes
f l=[sum[1|t<-mapM(\x->[1..x])l,sum t==k]|k<-[length l..sum l]]
Haskell, 68 bytes
k%(h:t)=sum$map(%t)[k-h..k-1]
k%_=0^k^2
f l=map(%l)[length l..sum l]
Jelly, 14 bytes
R+Ѐ/FċЀSR$ḟ0
Input is a list of die values. I could golf this down by stealing ĠL€ from the other Jelly answer but then I could also golf down the first half and end up with the same thing so I'll just leave it how it is
Jelly, 14 7 bytes
-3 bytes thanks to Mr. Xcoder (use of an implicit range to avoid leading R; replacement of reduce by the dyadic Cartesian product and flatten, p/F€, with the Cartesian product built-in for that very purpose, Œp.)
ŒpS€ĠL€
A monadic link taking a list of dice faces and returning the normalised distribution of the increasing sums.
How?
Goes through the list of dice "sizes" (implicitly) makes them into their list of faces, then gets the Cartesian product of those lists (all possible rolls of the set of dice), then sums up those rolls, gets the groups of equal indices (by ascending value) and takes the length of each group.
ŒpS€ĠL€ - Link: list of numbers, dice e.g. [2,5,1,2]
Œp - Cartisian product (implicit range-ification -> [[1,2],[1,2,3,4,5],[1],[1,2]])
- -> [[1,1,1,1],[1,1,1,2],[1,2,1,1],[1,2,1,2],[1,3,1,1],[1,3,1,2],[1,4,1,1],[1,4,1,2],[1,5,1,1],[1,5,1,2],[2,1,1,1],[2,1,1,2],[2,2,1,1],[2,2,1,2],[2,3,1,1],[2,3,1,2],[2,4,1,1],[2,4,1,2],[2,5,1,1],[2,5,1,2]]
S€ - sum €ach -> [4,5,5,6,6,7,7,8,8,9,5,6,6,7,7,8,8,9,9,10]
Ġ - group indices -> [[1],[2,3,11],[4,5,12,13],[6,7,14,15],[8,9,16,17],[10,18,19],[20]]
L€ - length of €ach -> [1,3,4,4,4,3,1]
Note: there is only ever one way to roll the minimum (by rolling a one on each and every dice) and we are not double-counting any rolls, so there is no need to perform a GCD normalisation.
Pyth, 12 bytes
lM.gs.nk*FSM
How?
lM.gs.nk*FSM ~ Full program.
SM ~ Map with inclusive unary integer range [1, N].
*F ~ Fold (Reduce by) Cartesian product.
.g ~ Group by function result.
s.n ~ The sum of the list when flattened.
lM ~ Length of each group.