sourcelibs/Combinatorics/src/Combinatorics.xtl

1⍝# Combinatorics: counting and listing -- factorials, binomials, 2⍝# combinations, permutations, subsets, Cartesian products. 3⍝# Import it with an alias of your choice: "cb:" u_se< "Combinatorics". 4⍝# Put libs/Combinatorics/src on XETAL_PATH ("just path"); the reference is libs/Combinatorics/docs. 5⍝# Names with l: are exported; those under h: are private to this file. 6⍝# 7⍝# Lists come as matrices, one combination (or permutation, subset, 8⍝# pair) per row, in lexicographic order. 9 10⍝## Counting 11 12⍝# f_actorial n: n!, item by item (0! is 1). 13ˡf̲actorial ← { n → '{ '× r̲/ r̲ange ⍵ } e̲ach n } 14 15⍝# C(n, k) for one k and n, exactly: C(n, j) = C(n, j - 1) * (n - j + 1) / j. 16ʰc̲h ← { k n → 17 (k < 0) ∨ k > n ? 0 18 j ← k m̲in n − k 19 j = 0 ? 1 20 ((1 + n − j) × (j − 1) ʰc̲h n) d̲iv j 21} 22 23⍝# k c_hoose n: how many ways to choose k things of n, item by item. 24ˡc̲hoose ← { k n → k 'ʰc̲h e̲ach n } 25 26⍝## Listing 27 28⍝# k c_ombinations n: every choice of k of 1..n, one per row, in 29⍝# lexicographic order (dfns cmat). 30ˡc̲ombinations ← { k n → 31 (k < 0) ∨ k > n ? (0 c̲at k) r̲eshape 0 32 k = 0 ? 1 0 r̲eshape 0 33 k = n ? (1 c̲at n) r̲eshape r̲ange n 34 (1 c̲at₂ 1 + (k − 1) ˡc̲ombinations n − 1) c̲at 1 + k ˡc̲ombinations n − 1 35} 36 37⍝# The rows of P (permutations of 1..n-1) with i put first and the 38⍝# others renumbered around it. 39ʰf̲irstThen ← { i p → i c̲at₂ p + p ≥ i } 40 41⍝# p_ermutations n: every ordering of 1..n, one per row, in 42⍝# lexicographic order (dfns pmat). 43ˡp̲ermutations ← { n → 44 n ≤ 1 ? (1 c̲at n) r̲eshape 1 45 p ← ˡp̲ermutations n − 1 46 d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at d̲isclose ⍵ } r̲/ '{ i → i ʰf̲irstThen p } m̲ap r̲ange n 47} 48 49⍝# s_ubsets n: every subset of 1..n as a mask, one per row: 2^n rows, 50⍝# counting in binary (the empty set first). 51ˡs̲ubsets ← { n → o̲\ (n r̲eshape 2) e̲ncode o̲ffsets 2 ^ n } 52 53⍝# p_owerset v: every subset of the items of v, as a list (Box), in 54⍝# the order of s_ubsets. 55ˡp̲owerset ← { v → 56 m ← ˡs̲ubsets t̲ally v 57 '{ i → (i s̲elect m) r̲eplicate v } m̲ap r̲ange t̲ally m 58} 59 60⍝# a p_roduct b: every pair of an item of a with one of b, one per row 61⍝# (a's items vary slowest). 62ˡp̲roduct ← { a b → 63 n ← (t̲ally a) × t̲ally b 64 o̲\ (2 c̲at n) r̲eshape ((t̲ally b) r̲eplicate a) c̲at n r̲eshape b 65}