m-nomial coefficient
Perl, 63 60 59 57 bytes
Includes +2 for -pa
Give input parameters on STDIN
mnomial.pl <<< "3 5 6"
#!/usr/bin/perl -pa
$_=/-/^($_--,1x$F[2])=~/^(1{0,$_}){$F[1]}$(??{++$;})/+$
As a perl programmer I just know that every problem is really a regex in disguise...
Explanation:
m(3,5,6) can be seen as the number of ways you can get 6 by adding 5 integers in the range [0..2]
. You can write a regex matching such a partition using:
1 x 6 = /^(1{0,2}){5}$/
However once a single solution is found the regex stops. We need to fail the found solution to get the regex to backtrack to the next solution and count the failures. In perl this can be done by extending the regex at runtime with something that is sure to fail, e.g. by demanding that something comes after the end of the string:
1 x 6 = /^(1{0,2}){5}$(??{++$n})/
$n will count the number of failed attempts
My solution is basically this with two modifications:
- Output the counter in such a way that you get
0
instead of the empty string if there is no valid partition and the counter never gets incremented - If the third argument is negative it would work if negative string lengths existed, but 1 x -5 is the empty string and 0 can be written exactly one way as sum of zeros, so that would output 1 instead of 0. I xor with the result of
/-/
to change the 1 back to 0
Without the need to handle a negative third argument this 49 byte solution would be good enough (give one parameter of m(x,y,z)
on each line of STDIN in order y \n z \n x \n
):
#!/usr/bin/perl -pa
$_=(1x<>)=~/^(1{0,@{[<>-1]}}){@F}$(??{++$;})/+$
Jelly, 6 bytes
ṗ’S€ċ⁵
This is a full program that accepts m, n and the exponent as separate command line arguments.
Try it online!
How it works
The problem boils down to counting the number of ways we can express the exponent as an ordered sum of exactly n integers between 0 and m - 1 (both inclusive).
ṗ’S€ċ⁵ Main link. Arguments: m, n, k
ṗ Cartesian product; yield the array of all lists of exactly n elements of
[1, ..., m].
’ Decrement all integers in the resulting 2D list.
S€ Compute the sum of each individual list.
⁵ Yield k.
ċ Count the number of times k appears in the list of sums.
Pyth, 29 8 bytes
/sM^UQEE
Try it online!
Uses Dennis' Method.
If the input can be rearranged so that m(3,5,6)
is fed in the order of 6,3,5
into the program, an extra byte can be cut off:
/sM^UEE
Try it online!
Original 29-byte approach
.N?|TY?|<Y0>Y*tNT0sm:NtT-YdN1
Test suite.
How it works:
Uses the recurrence formula m(k,n,r) = m(k,n-1,r) + m(k,n-1,r-1) + ... m(k,n-1,r-k+1)
.
.N?|TY?|<Y0>Y*tNT0sm:NtT-YdN1
.N def colon(N,T,Y):
?|TY if T or Y:
?|<Y0>Y*tNT if Y<0 or Y>(N-1)*T:
0 return 0
else:
sm:NtT-YdN return sum([colon(N,T-1,Y-d) for d in range(N)])
else:
1 return 1