@@ -39,6 +39,10 @@ of items.
39
39
Example: (permutations [1 2 3]) -> ((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1))
40
40
Example: (permutations [1 1 2]) -> ((1 1 2) (1 2 1) (2 1 1))
41
41
42
+ (count-permutations items) - (count (permutations items)), but computed more directly
43
+ (nth-permutation items) - (nth (permutations items)), but computed more directly
44
+ (permutation-index items) - Returns the number n where (nth-permutation (sort items) n) is items
45
+
42
46
(partitions items) - A lazy sequence of all the partitions
43
47
of items.
44
48
Example: (partitions [1 2 3]) -> (([1 2 3])
@@ -71,31 +75,57 @@ Most of these algorithms are derived from algorithms found in Knuth's wonderful
71
75
[n cnt]
72
76
(lazy-seq
73
77
(let [c (vec (cons nil (for [j (range 1 (inc n))] (+ j cnt (- (inc n)))))),
74
- iter-comb
75
- (fn iter-comb [c j]
76
- (if (> j n) nil
77
- (let [c (assoc c j (dec (c j)))]
78
- (if (< (c j) j) [c (inc j)]
79
- (loop [c c, j j]
80
- (if (= j 1 ) [c j]
81
- (recur (assoc c (dec j) (dec (c j))) (dec j)))))))),
82
- step
83
- (fn step [c j]
84
- (cons (rseq (subvec c 1 (inc n)))
85
- (lazy-seq (let [next-step (iter-comb c j)]
86
- (when next-step (step (next-step 0 ) (next-step 1 )))))))]
87
- (step c 1 ))))
78
+ iter-comb
79
+ (fn iter-comb [c j]
80
+ (if (> j n) nil
81
+ (let [c (assoc c j (dec (c j)))]
82
+ (if (< (c j) j) [c (inc j)]
83
+ (loop [c c, j j]
84
+ (if (= j 1 ) [c j]
85
+ (recur (assoc c (dec j) (dec (c j))) (dec j)))))))),
86
+ step
87
+ (fn step [c j]
88
+ (cons (rseq (subvec c 1 (inc n)))
89
+ (lazy-seq (let [next-step (iter-comb c j)]
90
+ (when next-step (step (next-step 0 ) (next-step 1 )))))))]
91
+ (step c 1 ))))
92
+
93
+ (defn- index-combinations2 ; Algorithm T
94
+ [n cnt]
95
+ (lazy-seq
96
+ (let [c (vec (concat [nil ]
97
+ (for [j (range 1 (inc n))] (dec j))
98
+ [cnt 0 ]))
99
+ iter-comb
100
+ (fn iter-comb [c j x]
101
+ (let [c1+1 (inc (c 1 ))]
102
+ (if (< c1+1 (c 2 ))
103
+ [(assoc c 1 c1+1) (c 2 ) x]
104
+ (loop [c c, j j, x x]
105
+ (let [c (assoc c (dec j) (- j 2 )),
106
+ x (inc (c j))]
107
+ (cond
108
+ (= x (c (inc j))) (recur c (inc j) x)
109
+ (> j n) nil
110
+ :else [(assoc c j x) (dec j) x]))))))
111
+ step
112
+ (fn step [c j x]
113
+ (cons (subvec c 1 (inc n))
114
+ (lazy-seq (let [next-step (iter-comb c j x)]
115
+ (when next-step (step (next-step 0 ) (next-step 1 ) (next-step 2 )))))))]
116
+ (step c n n))))
88
117
89
118
(defn combinations
90
119
" All the unique ways of taking n different elements from items"
91
120
[items n]
92
- (let [v-items (vec ( reverse items) )]
121
+ (let [v-items (vec items)]
93
122
(if (zero? n) (list ())
94
- (let [cnt (count items)]
95
- (cond (> n cnt) nil
96
- (= n cnt) (list (seq items))
97
- :else
98
- (map #(map v-items %) (index-combinations n cnt)))))))
123
+ (let [cnt (count items)]
124
+ (cond (> n cnt) nil
125
+ (= n 1 ) (for [item items] (list item))
126
+ (= n cnt) (list (seq items))
127
+ :else
128
+ (map #(map v-items %) (index-combinations2 n cnt)))))))
99
129
100
130
(defn- unchunk
101
131
" Given a sequence that may have chunks, return a sequence that is 1-at-a-time
@@ -106,31 +136,31 @@ which increases the amount of memory in use that cannot be garbage
106
136
collected."
107
137
[s]
108
138
(lazy-seq
109
- (when (seq s)
110
- (cons (first s) (unchunk (rest s))))))
139
+ (when (seq s)
140
+ (cons (first s) (unchunk (rest s))))))
111
141
112
142
(defn subsets
113
143
" All the subsets of items"
114
144
[items]
115
145
(mapcat (fn [n] (combinations items n))
116
- (unchunk (range (inc (count items))))))
146
+ (unchunk (range (inc (count items))))))
117
147
118
148
(defn cartesian-product
119
149
" All the ways to take one item from each sequence"
120
150
[& seqs]
121
151
(let [v-original-seqs (vec seqs)
122
- step
123
- (fn step [v-seqs]
124
- (let [increment
125
- (fn [v-seqs]
126
- (loop [i (dec (count v-seqs)), v-seqs v-seqs]
127
- (if (= i -1 ) nil
128
- (if-let [rst (next (v-seqs i))]
129
- (assoc v-seqs i rst)
130
- (recur (dec i) (assoc v-seqs i (v-original-seqs i)))))))]
131
- (when v-seqs
132
- (cons (map first v-seqs)
133
- (lazy-seq (step (increment v-seqs)))))))]
152
+ step
153
+ (fn step [v-seqs]
154
+ (let [increment
155
+ (fn [v-seqs]
156
+ (loop [i (dec (count v-seqs)), v-seqs v-seqs]
157
+ (if (= i -1 ) nil
158
+ (if-let [rst (next (v-seqs i))]
159
+ (assoc v-seqs i rst)
160
+ (recur (dec i) (assoc v-seqs i (v-original-seqs i)))))))]
161
+ (when v-seqs
162
+ (cons (map first v-seqs)
163
+ (lazy-seq (step (increment v-seqs)))))))]
134
164
(when (every? seq seqs)
135
165
(lazy-seq (step v-original-seqs)))))
136
166
@@ -143,18 +173,18 @@ collected."
143
173
144
174
(defn- iter-perm [v]
145
175
(let [len (count v),
146
- j (loop [i (- len 2 )]
147
- (cond (= i -1 ) nil
148
- (< (v i) (v (inc i))) i
149
- :else (recur (dec i))))]
176
+ j (loop [i (- len 2 )]
177
+ (cond (= i -1 ) nil
178
+ (< (v i) (v (inc i))) i
179
+ :else (recur (dec i))))]
150
180
(when j
151
181
(let [vj (v j),
152
- l (loop [i (dec len)]
153
- (if (< vj (v i)) i (recur (dec i))))]
154
- (loop [v (assoc v j (v l) l vj), k (inc j), l (dec len)]
155
- (if (< k l)
156
- (recur (assoc v k (v l) l (v k)) (inc k) (dec l))
157
- v))))))
182
+ l (loop [i (dec len)]
183
+ (if (< vj (v i)) i (recur (dec i))))]
184
+ (loop [v (assoc v j (v l) l vj), k (inc j), l (dec len)]
185
+ (if (< k l)
186
+ (recur (assoc v k (v l) l (v k)) (inc k) (dec l))
187
+ v))))))
158
188
159
189
(defn- vec-lex-permutations [v]
160
190
(when v (cons v (lazy-seq (vec-lex-permutations (iter-perm v))))))
@@ -166,10 +196,10 @@ In prior versions of the combinatorics library, there were two similar functions
166
196
{:deprecated " 1.3" }
167
197
[c]
168
198
(lazy-seq
169
- (let [vec-sorted (vec (sort c))]
170
- (if (zero? (count vec-sorted))
171
- (list [])
172
- (vec-lex-permutations vec-sorted)))))
199
+ (let [vec-sorted (vec (sort c))]
200
+ (if (zero? (count vec-sorted))
201
+ (list [])
202
+ (vec-lex-permutations vec-sorted)))))
173
203
174
204
(defn- sorted-numbers?
175
205
" Returns true iff s is a sequence of numbers in non-decreasing order"
@@ -181,24 +211,207 @@ In prior versions of the combinatorics library, there were two similar functions
181
211
" Handles the case when you want the permutations of a list with duplicate items."
182
212
[l]
183
213
(let [f (frequencies l),
184
- v (vec (keys f )),
214
+ v (vec (distinct l )),
185
215
indices (apply concat
186
216
(for [i (range (count v))]
187
217
(repeat (f (v i)) i)))]
188
218
(map (partial map v) (lex-permutations indices))))
189
-
219
+
190
220
(defn permutations
191
- " All the distinct permutations of items, lexicographic by index."
221
+ " All the distinct permutations of items, lexicographic by index
222
+ (special handling for duplicate items)."
192
223
[items]
193
224
(cond
194
- (sorted-numbers? items) (lex-permutations items),
195
-
196
- (apply distinct? items)
197
- (let [v (vec items)]
198
- (map #(map v %) (lex-permutations (range (count v)))))
225
+ (sorted-numbers? items) (lex-permutations items),
226
+
227
+ (apply distinct? items)
228
+ (let [v (vec items)]
229
+ (map #(map v %) (lex-permutations (range (count v)))))
230
+
231
+ :else
232
+ (multi-perm items)))
233
+
234
+ ; ; Jumping directly to a given permutation
235
+
236
+ ; ; First, let's deal with the case where all items are distinct
237
+ ; ; This is the easier case.
238
+
239
+ (defn- factorial-numbers
240
+ " Input is a non-negative base 10 integer, output is the number in the
241
+ factorial number system (http://en.wikipedia.org/wiki/Factorial_number_system)
242
+ expressed as a list of 'digits'"
243
+ [n]
244
+ {:pre [(integer? n) (not (neg? n))]}
245
+ (loop [n n, digits (), divisor 1 ]
246
+ (if (zero? n)
247
+ digits
248
+ (let [q (quot n divisor), r (rem n divisor)]
249
+ (recur q (cons r digits) (inc divisor))))))
250
+
251
+ (defn- factorial [n]
252
+ {:pre [(integer? n) (not (neg? n))]}
253
+ (loop [acc 1 , n n]
254
+ (if (zero? n) acc (recur (*' acc n) (dec n)))))
255
+
256
+ (defn- remove-nth [l n]
257
+ (loop [acc [], l l, n n]
258
+ (if (zero? n) (into acc (rest l))
259
+ (recur (conj acc (first l)) (rest l) (dec n)))))
260
+
261
+ (defn- nth-permutation-distinct
262
+ " Input should be a sorted sequential collection l of distinct items,
263
+ output is nth-permutation (0-based)"
264
+ [l n]
265
+ (assert (< n (factorial (count l)))
266
+ (format " %s is too large. Input has only %s permutations."
267
+ (str n) (str (factorial (count l)))))
268
+ (let [length (count l)
269
+ fact-nums (factorial-numbers n)]
270
+ (loop [indices (concat (repeat (- length (count fact-nums)) 0 )
271
+ fact-nums),
272
+ l l
273
+ perm []]
274
+ (if (empty? indices) perm
275
+ (let [i (first indices),
276
+ item (nth l i)]
277
+ (recur (rest indices) (remove-nth l i) (conj perm item)))))))
278
+
279
+ ; ; Now we generalize to collections with duplicates
280
+
281
+ (defn- count-permutations-from-frequencies [freqs]
282
+ (let [counts (vals freqs)]
283
+ (reduce / (factorial (apply + counts))
284
+ (map factorial counts ))))
285
+
286
+ (defn count-permutations
287
+ " Counts the number of distinct permutations of l"
288
+ [l]
289
+ (count-permutations-from-frequencies (frequencies l)))
290
+
291
+ (defn- initial-perm-numbers
292
+ " Takes a sorted frequency map and returns how far into the sequence of
293
+ lexicographic permutations you get by varying the first item"
294
+ [freqs]
295
+ (reductions + 0
296
+ (for [[k v] freqs]
297
+ (count-permutations-from-frequencies (assoc freqs k (dec v))))))
298
+
299
+ ; ; Explanation of initial-perm-numbers:
300
+ ; (initial-perm-numbers (sorted-map 1 2, 2 1)) => (0 2 3) because when
301
+ ; doing the permutations of [1 1 2], there are 2 permutations starting with 1
302
+ ; and 1 permutation starting with 2.
303
+ ; So the permutations starting with 1 begin with the 0th permutation
304
+ ; and the permutations starting with 2 begin with the 2nd permutation
305
+ ; (The final 3 denotes the total number of permutations).
306
+
307
+ (defn- index-remainder
308
+ " Finds the index and remainder from the initial-perm-numbers."
309
+ [perm-numbers n]
310
+ (loop [perm-numbers perm-numbers
311
+ index 0 ]
312
+ (if (and (<= (first perm-numbers) n)
313
+ (< n (second perm-numbers)))
314
+ [index (- n (first perm-numbers))]
315
+ (recur (rest perm-numbers) (inc index)))))
316
+
317
+ ; ; Explanation of index-remainder:
318
+ ; (index-remainder [0 6 9 11] 8) => [1 2]
319
+ ; because 8 is (+ (nth [0 6 9 11] 1) 2)
320
+ ; i.e., 1 gives us the index into the largest number smaller than n
321
+ ; and 2 is the remaining amount needed to sum up to n.
322
+
323
+ (defn- dec-key [m k]
324
+ (if (= 1 (m k))
325
+ (dissoc m k)
326
+ (update-in m [k] dec)))
327
+
328
+ (defn- factorial-numbers-with-duplicates
329
+ " Input is a non-negative base 10 integer n, and a sorted frequency map freqs.
330
+ Output is a list of 'digits' in this wacky duplicate factorial number system"
331
+ [n freqs]
332
+ (loop [n n, digits [], freqs freqs]
333
+ (if (zero? n) (into digits (repeat (apply + (vals freqs)) 0 ))
334
+ (let [[index remainder]
335
+ (index-remainder (initial-perm-numbers freqs) n)]
336
+ (recur remainder (conj digits index)
337
+ (let [nth-key (nth (keys freqs) index)]
338
+ (dec-key freqs nth-key)))))))
339
+
340
+ (defn- nth-permutation-duplicates
341
+ " Input should be a sorted sequential collection l of distinct items,
342
+ output is nth-permutation (0-based)"
343
+ [l n]
344
+ (assert (< n (count-permutations l))
345
+ (format " %s is too large. Input has only %s permutations."
346
+ (str n) (str (count-permutations l))))
347
+ (loop [freqs (into (sorted-map ) (frequencies l)),
348
+ indices (factorial-numbers-with-duplicates n freqs)
349
+ perm []]
350
+ (if (empty? indices) perm
351
+ (let [i (first indices),
352
+ item (nth (keys freqs) i)]
353
+ (recur (dec-key freqs item)
354
+ (rest indices)
355
+ (conj perm item))))))
356
+
357
+ ; ; Now we create the public version, which detects which underlying algorithm to call
199
358
200
- :else
201
- (multi-perm items)))
359
+ (defn nth-permutation
360
+ " (nth (permutations items)) but calculated more directly."
361
+ [items n]
362
+ (if (sorted-numbers? items)
363
+ (if (apply distinct? items)
364
+ (nth-permutation-distinct items n)
365
+ (nth-permutation-duplicates items n))
366
+ (if (apply distinct? items)
367
+ (let [v (vec items),
368
+ perm-indices (nth-permutation-distinct (range (count items)) n)]
369
+ (vec (map v perm-indices)))
370
+ (let [v (vec (distinct items)),
371
+ f (frequencies items),
372
+ indices (apply concat
373
+ (for [i (range (count v))]
374
+ (repeat (f (v i)) i)))]
375
+ (vec (map v (nth-permutation-duplicates indices n)))))))
376
+
377
+ ; ; Now let's go the other direction, from a sortable collection to the nth
378
+ ; ; position in which we would find the collection in the lexicographic sequence
379
+ ; ; of permutations
380
+
381
+ (defn- list-index
382
+ " The opposite of nth, i.e., from an item in a list, find the n"
383
+ [l item]
384
+ (loop [l l, n 0 ]
385
+ (assert (seq l))
386
+ (if (= item (first l)) n
387
+ (recur (rest l) (inc n)))))
388
+
389
+ (defn- permutation-index-distinct
390
+ [l]
391
+ (loop [l l, index 0 , n (dec (count l))]
392
+ (if (empty? l) index
393
+ (recur (rest l)
394
+ (+ index (* (factorial n) (list-index (sort l) (first l))))
395
+ (dec n)))))
396
+
397
+ (defn- permutation-index-duplicates
398
+ [l]
399
+ (loop [l l, index 0 , freqs (into (sorted-map ) (frequencies l))]
400
+ (if (empty? l) index
401
+ (recur (rest l)
402
+ (reduce + index
403
+ (for [k (take-while #(neg? (compare % (first l))) (keys freqs))]
404
+ (count-permutations-from-frequencies (dec-key freqs k))))
405
+ (dec-key freqs (first l))))))
406
+
407
+ (defn permutation-index
408
+ " Input must be a sortable collection of items. Returns the n such that
409
+ (nth-permutation (sort items) n) is items."
410
+ [items]
411
+ (if (apply distinct? items)
412
+ (permutation-index-distinct items)
413
+ (permutation-index-duplicates items)))
414
+
202
415
203
416
; ;;;; Partitions, written by Alex Engelberg; adapted from Knuth Volume 4A
204
417
0 commit comments