Skip to content

Instantly share code, notes, and snippets.

@dprelec
Last active February 14, 2021 21:48
Show Gist options
  • Save dprelec/1afc59f3184b38dc8a64 to your computer and use it in GitHub Desktop.
Save dprelec/1afc59f3184b38dc8a64 to your computer and use it in GitHub Desktop.
Implementation of lexical permutation algorithm
;; Knuth's algorithm for lexical permutations.
;; For now works on numerical vectors only.
;;
;; Description of the algorithm:
;; http://www-cs-faculty.stanford.edu/~uno/fasc2b.ps.gz
;;
;; dprelec, 2014-05-28
(defn find-j [nums]
(loop [j (- (count nums) 2)]
(if (and (>= j 0) (>= (nums j) (nums (+ 1 j))))
(recur (dec j))
(if (< j 0)
nil
j))))
(defn find-l [j nums]
(loop [l (- (count nums) 1)]
(if (>= (nums j) (nums l))
(recur (dec l))
l)))
(defn swap [nums i j]
(let [t (nums j)
f (assoc nums j (nums i))
s (assoc f i t)]
s))
(defn swap-others [nums j]
(loop [k (inc j) l (- (count nums) 1) nums nums]
(if (< k l)
(recur (inc k) (dec l) (swap nums k l))
nums)))
(defn next-permutation [nums]
(let [j (find-j nums)]
(if-not (nil? j)
(let [l (find-l j nums) nums (swap nums j l)]
(swap-others nums j))
nil)))
(defn list-all-permutations [nums]
(loop [p [nums] nums nums]
(let [nextp (next-permutation nums)]
(if-not (nil? nextp)
(recur (conj p nextp) nextp)
p))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment