(defn permutation-sequence
"Produces an iterable sequence developing the permutations of the input sequence
of objects (which are considered distinct) in church-bell-changes order - that
is, each permutation differs from the previous by a transposition of adjacent
elements (Algorithm P from §7.2.1.2 of Knuth).
This is an unusual way to go about this in a functional language, but it's
fun.
This approach has the side-effect of arranging for the parity of the generated
permutations to alternate; the first permutation yielded is the identity
permutation (which of course is even).
Inside, there is a great deal of mutable state, but this cannot be observed by
the user."
[as]
(let [n (count as)
a (object-array as)
c (int-array n (repeat 0))
o (int-array n (repeat 1))
return #(into [] %)
the-next (atom (return a))
has-next (atom true)
step (fn [j s]
(let [q (int (+ (aget c j) (aget o j)))]
(cond (< q 0)
(do
(aset o j (int (- (aget o j))))
(recur (dec j) s))
(= q (inc j))
(if (zero? j)
false
(do (aset o j (int (- (aget o j))))
(recur (dec j) (inc s))))
:else
(let [i1 (+ s (- j (aget c j)))
i2 (+ s (- j q))
t (aget a i1)]
(aset a i1 (aget a i2))
(aset a i2 t)
(aset c j q)
true
))))]
(#?(:clj iterator-seq :cljs #'cljs.core/chunkIteratorSeq)
(reify #?(:clj java.util.Iterator :cljs Object)
(hasNext [_] @has-next)
(next [_]
(let [prev @the-next]
(reset! has-next (step (dec n) 0))
(reset! the-next (return a))
prev))
#?@(:cljs
[IIterable
(-iterator [this] this)])))))