1 module des.math.combin.count; 2 3 import des.ts; 4 5 version(unittest) import std..string : format; 6 7 /// factorial 8 long fact( long n ) pure nothrow 9 in { assert( n >= 0 ); } 10 out(res) { assert( res >= 0 ); } 11 body 12 { 13 if( n <= 2 ) return n; 14 long res = 1; 15 foreach( i; 2 .. n+1 ) res *= i; 16 return res; 17 } 18 19 unittest 20 { 21 assertEq( fact(0), 0 ); 22 assertEq( fact(1), 1 ); 23 assertEq( fact(2), 2 ); 24 assertEq( fact(3), 6 ); 25 assertEq( fact(4), 24 ); 26 assertEq( fact(5), 120 ); 27 assertEq( fact(6), 720 ); 28 assertEq( fact(7), 5040 ); 29 assertEq( fact(8), 40320 ); 30 assertEq( fact(9), 362880 ); 31 assertEq( fact(10), 3628800 ); 32 } 33 34 /// equals to fact(n) / ( fact(k) * fact( n-k ) ) 35 long combinationCount( long n, long k ) pure nothrow 36 in 37 { 38 assert( k > 0 ); 39 assert( n >= 0 ); 40 } 41 out(res) { assert( res >= 0 ); } 42 body 43 { 44 if( k == 1 || k == n-1 ) return n; 45 long a = n * (n-1); 46 long b = k; 47 48 foreach( i; 2 .. k ) 49 { 50 a *= (n-i); 51 b *= i; 52 } 53 54 return a / b; 55 } 56 57 unittest 58 { 59 static pure nothrow long comb2( long n, long k ) 60 { return fact(n) / ( fact(k) * fact( n-k ) ); } 61 62 foreach( k; 1 .. 10 ) 63 assertEq( combinationCount(10,k), comb2(10,k), 64 format( "equal test fails with k==%d, %%s != %%s", k ) ); 65 } 66 67 /// equals to fact(n) / fact(n-k) 68 long partialPermutationCount( long n, long k ) pure nothrow 69 in 70 { 71 assert( k > 0 ); 72 assert( n >= k ); 73 } 74 out(res) { assert( res >= 0 ); } 75 body 76 { 77 if( k == 1 ) return n; 78 79 long res = n * (n-1); 80 81 foreach( i; 2 .. k ) 82 res *= (n-i); 83 84 return res; 85 } 86 87 unittest 88 { 89 static pure nothrow long perm2( long n, long k ) 90 { return fact(n) / fact( n-k ); } 91 92 foreach( k; 1 .. 10 ) 93 assertEq( partialPermutationCount(10,k), perm2(10,k), 94 format( "equal test fails with k==%d, %%s != %%s", k ) ); 95 }