1. Permutation and Combination
data null;
n = 5;
r = 2;*the factorial of a number;
fact=fact(n);*for positive integers, fact(n) = gamma(n+1);
gamm=gamma(n + 1);*C(n,r): number of combinations of n objects selected r ;
*n! / [r!(n-r)!];
comb1 = comb(n,r);
comb2 = fact(n) / (fact® * fact(n-r));
comb3 = gamma(n+1) / (gamma(r+1) * gamma(n-r+1));
comb4 = exp(lcomb(n,r));
comb5 = exp(lgamma(n+1)-lgamma(r+1)-lgamma(n-r+1));*A(n,r): number of permutation (ordered arrangements);
*n! / (n-r)!;
perm1 = perm(n,r);
perm2 = fact(n) / fact(n-r);
perm3 = gamma(n+1) / gamma(n-r+1);
perm4 = exp(lperm(n,r));
perm5 = exp(lgamma(n+1)-lgamma(n-r+1));put (all) (= / );
run;
Note functions fact() and gamm() can quickly reach out their limitations(try n=171 and check the overflow notes in Log window).
2. Generate Unique Pairs
Question see here.
data null;
array x[5] $1 (“A” “C” “D” “B” “E”);
n = dim(x);
r = 2;
ncomb = comb(n, r);
do j = 1 to ncomb+1;
rc = allcomb(j, r, of x[*]);
if rc < 0 then leave;
put j 5. +3 x1 “- ” x2 +3;
end;
run;
The output in Log:
1 A – C
2 A – E
3 A – B
4 A – D
5 C – D
6 C – E
7 C – B
8 D – B
9 D – E
10 B – E
Or if you like alphabetical sorted pairs:
data null;
array x[5] $1 (“A” “C” “D” “B” “E”);
n = dim(x);
r = 2;
ncomb = comb(n, r);
do j = 1 to ncomb+1;
rc = lexcomb(j, r, of x[*]);
if rc < 0 then leave;
put j 5. +3 x1 “- ” x2 +3;
end;
run;
The output:
1 A – B
2 A – C
3 A – D
4 A – E
5 B – C
6 B – D
7 B – E
8 C – D
9 C – E
10 D – E
I checked Rick Wicklin’s blog and found PROC IML offers a much more intuitive approach to this problem:
proc iml;
n = 5;
r = 2;
idx = allcomb(n, r);
print idx;
quit;
The output:
1 2
2 3
1 3
3 4
2 4
1 4
4 5
3 5
2 5
1 5
or make the output more readable:
proc iml;
n = 5;
r = 2;
idx = allcomb(n, r);
print idx;Items = {“A” “C” “D” “B” “E”};
S = Items[ ,idx];
S = shape(S, 0, r);
print S[r=(char(1:nrow(S)))];
quit;
the output:
1 A C
2 C D
3 A D
4 D B
5 C B
6 A B
7 B E
8 D E
9 C E
10 A E
3. Generate Unique Pairs: A Macro
Years ago when the build-in functions above might not be available in SAS, a macro %combo did the same job:
%combo(2,a,c,d,b,e)
The output:
1 a c
2 a d
3 a b
4 a e
5 c d
6 c b
7 c e
8 d b
9 d e
10 b e
It’s fun to check out the macro how to implement it by arrays.