Sounds like you want to number permutations:
(def factorial (reductions * 1 (drop 1 (range))))
(defn factoradic [n] {:pre [(>= n 0)]}
(loop [a (list 0) n n p 2]
(if (zero? n) a (recur (conj a (mod n p)) (quot n p) (inc p)))))
(defn nth-permutation [s n] {:pre [(< n (nth factorial (count s)))]}
(let [d (factoradic n)
choices (concat (repeat (- (count s) (count d)) 0) d)]
((reduce
(fn [m i]
(let [[left [item & right]] (split-at i (m :rem))]
(assoc m :rem (concat left right)
:acc (conj (m :acc) item))))
{:rem s :acc []} choices) :acc)))
Let's try it:
(def colours ["red" "blue" "green" "yellow" "cyan" "magenta" "black" "white"])
(nth-permutation colours 39038)
=> ["white" "magenta" "blue" "green" "cyan" "yellow" "red" "black"]
...as in the question, but without generating any of the other permutations.
Well enough, but would we get them all?
(def x (map (partial nth-permutation colours) (range (nth factorial (count colours)))))
(count x)
=> 40320
(count (distinct x))
=> 40320
(nth factorial (count colours))
=> 40320
Note the permutations are generated in (lexicographic by index) order:
user=> (pprint (take 24 x))
(["red" "blue" "green" "yellow" "cyan" "magenta" "black" "white"]
["red" "blue" "green" "yellow" "cyan" "magenta" "white" "black"]
["red" "blue" "green" "yellow" "cyan" "black" "magenta" "white"]
["red" "blue" "green" "yellow" "cyan" "black" "white" "magenta"]
["red" "blue" "green" "yellow" "cyan" "white" "magenta" "black"]
["red" "blue" "green" "yellow" "cyan" "white" "black" "magenta"]
["red" "blue" "green" "yellow" "magenta" "cyan" "black" "white"]
["red" "blue" "green" "yellow" "magenta" "cyan" "white" "black"]
["red" "blue" "green" "yellow" "magenta" "black" "cyan" "white"]
["red" "blue" "green" "yellow" "magenta" "black" "white" "cyan"]
["red" "blue" "green" "yellow" "magenta" "white" "cyan" "black"]
["red" "blue" "green" "yellow" "magenta" "white" "black" "cyan"]
["red" "blue" "green" "yellow" "black" "cyan" "magenta" "white"]
["red" "blue" "green" "yellow" "black" "cyan" "white" "magenta"]
["red" "blue" "green" "yellow" "black" "magenta" "cyan" "white"]
["red" "blue" "green" "yellow" "black" "magenta" "white" "cyan"]
["red" "blue" "green" "yellow" "black" "white" "cyan" "magenta"]
["red" "blue" "green" "yellow" "black" "white" "magenta" "cyan"]
["red" "blue" "green" "yellow" "white" "cyan" "magenta" "black"]
["red" "blue" "green" "yellow" "white" "cyan" "black" "magenta"]
["red" "blue" "green" "yellow" "white" "magenta" "cyan" "black"]
["red" "blue" "green" "yellow" "white" "magenta" "black" "cyan"]
["red" "blue" "green" "yellow" "white" "black" "cyan" "magenta"]
["red" "blue" "green" "yellow" "white" "black" "magenta" "cyan"])
nth
one without generating then-1
before it. Yes, you do this by implementing a decoding of Lehmer codes. I've taken a stab at this in my answer. – Cascara