Jump to content

Combinations with repetitions: Difference between revisions

Updated D code
(Updated D code)
Line 189:
=={{header|D}}==
Using [http://www-graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation lexicographic next bit permutation] to generate combinations with repetitions.
<lang d>import std.stdio, std.range ;
 
/*immutable*/ const struct CombRep {
immutable uint nt, nc ;
private /*immutable*/ ulong[] combVal;
 
this(in uint numType, in uint numChoice) pure nothrow {
assert(0 < numType && numType + numChoice <= 64,
"valid only for nt + nc <= 64 (ulong bit size)") ;
nt = numType ;
nc = numChoice ;
if (nc == 0) return ;
auto v = (1UL << (nt - 1)) - 1 return;
auto v = (1UL << (nt - 1)) - 1;
 
// init to smallest number that has nt-1 bit set
// a set bit is metaphored as a _type_ seperator
immutable limit = v << nc ;
 
// limit is the largest nt-1 bit set number that has nc zero-bit
// alimit zerois the largest nt-bit1 meansbit aset _choice_number betweenthat _type_has seperatorsnc
// zero-bit a zero-bit means a _choice_ between _type_
while(v <= limit) {
// combVal ~= v ;seperators
while if(v =<= 0limit) break ;{
auto tcombVal ~= (v | (v - 1)) + 1 ; // get next nt-1 bit number
v = t | ((((t & -t) /if (v &== -v0)) >> 1) - 1) ;
break;
// get next nt-1 bit number
immutable t = (v | (v - 1)) + 1;
v = t | ((((t & -t) / (v & -v)) >> 1) - 1);
}
}
 
uint length() @property { return combVal.length ; }
uint[] opIndexlength(uint idx) {@property returnconst val2set(combVal[idx])pure ;nothrow }{
uint length() @property { return combVal.length ; }
}
 
uint[] opIndex(in uint idx) const pure nothrow {
return val2set(combVal[idx]);
}
 
int opApply(int delegate(ref uint[]) dg) {
foreach (v; combVal) {
auto set = val2set(v) ;
if (dg(set))
break ;
}
return 1 ;
}
 
private uint[] val2set(in ulong v) const pure nothrow {
// convert bit pattern to selection set
immutable uint typeIdx = 0, bitLimit = nt + nc - 1 ;
uint[] settypeIdx = 0;
foreach(bitNum;uint[] 0..bitLimit)set;
foreach if(vbitNum; &0 (1 <<.. bitLimit - bitNum - 1))
if (v & (1 typeIdx++<< ;(bitLimit - bitNum - 1)))
typeIdx++;
else
set ~= typeIdx ;
return set ;
}
}
 
// forFor finite Random Access Range
auto combRep(R)(R types, in uint numChoice) /*pure nothrow*/
if if(hasLength!R && isRandomAccessRange!R) {
ElementType!R[][] result ;
 
foreach (s ; CombRep(types.length, numChoice)) {
ElementType!R[] r ;
foreach(iElementType!R[] r; s)
foreach r ~= types[(i]; ;s)
result ~= r ~= types[i];
while(vresult <~= limit) {r;
}
 
return result ;
}
 
void main() {
foreach (e; combRep(["iced", "jam", "plain"], 2))
// writefln("%5s", e) ;
writeln(e);
writeflnwriteln("Ways to select 3 from 10 types is %d", CombRep(10,3).length) ;
CombRep(10, 3).length);
}</lang>
output:
<pre>[ "iced", "iced"]
[ "iced", "jam"]
[ "iced", "plain"]
[ "jam", "jam"]
[ "jam", "plain"]
["plain", "plain"]
Ways to select 3 from 10 types is 220</pre>
 
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.