View Raw SPL
/*****************************************************************************
* *
* NCHOOSEK.SPL Copyright (C) 2014 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Computes binomial coefficient or returns all combinations *
* *
* Revisions: 8 Jun 2014 RRR Creation *
* *
*****************************************************************************/
#if @HELP_NCHOOSEK
NCHOOSEK
Purpose: Computes the binomial coefficient or returns all the
unordered combinations of the elements of the input series.
Syntax: NCHOOSEK(n, k)
n - A scalar or series. For a scalar, the binomial coefficient
is returned. For a series, all the unordered combinations
of the series elements are returned for k a positive
integer.
k - A scalar or series. If n is a series and k a positive
integer less than length(n), all the unordered combinations
of the series elements are returned.
Returns: A scalar or series, the number of combinations of n items
taken in unordreed groups of k, or if n is a series and k
a positive integer, the actual unordered combinations of
the series elements where each row represents a group of k
elements.
Example:
nchoosek(5, 3)
returns 10
Example:
c = nchoosek(1..5, 3)
c == {{1, 2, 3},
{1, 2, 4},
{1, 2, 5},
{1, 3, 4},
{1, 3, 5},
{1, 4, 5},
{2, 3, 4},
{2, 3, 5},
{2, 4, 5},
{3, 4, 5}}
Example:
nchoosek(5.3, 3)
returns 12.5345
Example:
nchoosek(3..5, 1..3)
returns {3, 6, 10}, the same as:
{nchoosek(3, 1), nchoosek(4, 2), nchoosek(5, 3)}
Remarks:
To return the actual combinations, N must be a series and
K must be an integer where 0 <= k <= length(n).
For scalar inputs N and K can be any value.
For integer values where 0 <= k <= n:
n n!
nchoosek(n, k) = ( ) = -----------
k k! (n - k)!
See BINCOEFF to return the generalized binomial coefficient
for any scalar or series inputs.
See Also:
Bincoeff
Factorial
Pascal
#endif
/* from n items, choose groups of k */
ITERATE nchoosek(v, k)
{
local c, i, m, n, p, r, cp, rp, nk;
if (argc < 2)
{
error("nchoosek - 2 input values required");
}
n = length(v);
if (n == 1 || length(k) > 1)
{
/* binomial coefficient for scalar or single value series */
return(bincoeff(v, k));
}
else if (floor(k) != real(k) || k < 0)
{
error("nchoosek - k must be a non-negative integer for n a series");
}
/* ensure integer k */
k = castint(k);
/* v is a series and k a positive integer */
if (k == 0 || k > n)
{
p = {};
}
else if (k == 1)
{
/* n x 1 */
p = v;
}
else if (k == 2)
{
r = repelem(v, n-1..-1..1);
p = serextract(v, 2..n, n-1..-1..1);
p = ravel(r, p);
}
else if (k == n)
{
/* 1 x n */
p = v';
}
else
{
/* iterate combinations back to front */
nk = 1..n-k+1;
rp = {};
p = v[k..n];
c = m = nk;
loop (i = 2..k)
{
cp = concat(rp, serextract(p, m, {-1}));
c = 1 + length(p) - c;
r = repelem(v[k-i+1..n-i+1], nk, c);
p = ravel(r, cp);
c = partsum(c);
m = 1 + c[1..n-k];
c = {1, m};
/* for speed, reference array, do not copy */
rp = refseries(p);
}
}
/* set to table */
setplotstyle(p, 4);
return(p);
}