random - 我可以在Clojure中进行确定性的随机播放吗?

标签 random clojure permutation shuffle deterministic

我想对集合进行一些改组,每次我的程序运行时它们都是一样的:

这是一种实现方法:

(def colours ["red" "blue" "green" "yellow" "cyan" "magenta" "black" "white"])

(defn colour-shuffle [n] 
  (let [cs (nth (clojure.math.combinatorics/permutations colours) n)]
    [(first cs) (drop 1 cs)]))

; use (rand-int 40320) to make up numbers, then hard code:
(def colour-shuffle-39038 (colour-shuffle 39038))
(def colour-shuffle-28193 (colour-shuffle 28193))
(def colour-shuffle-5667  (colour-shuffle 5667))
(def colour-shuffle-8194  (colour-shuffle 8194))
(def colour-shuffle-13895 (colour-shuffle 13895))
(def colour-shuffle-2345  (colour-shuffle 2345))

colour-shuffle-39038 ; ["white" ("magenta" "blue" "green" "cyan" "yellow" "red" "black")]

但是评估需要一些时间,而且看起来很浪费而且很微不足道。

是否有某种方法可以直接生成洗牌39038,而无需生成和使用所有序列?

(我已经意识到我可以对它们进行硬编码,或者将精力花在使用宏进行编译时。这似乎也有些垃圾。)

最佳答案

听起来像您想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)))

让我们尝试一下:
(def colours ["red" "blue" "green" "yellow" "cyan" "magenta" "black" "white"])

(nth-permutation colours 39038)
=> ["white" "magenta" "blue" "green" "cyan" "yellow" "red" "black"]

...就像问题中一样,但没有生成任何其他排列。

很好,但是我们能全部得到吗?
(def x (map (partial nth-permutation colours) (range (nth factorial (count colours)))))

(count x)
=> 40320
(count (distinct x))
=> 40320
(nth factorial (count colours))
=> 40320

请注意,排列是按(按索引的字典顺序)顺序生成的:
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"])

关于random - 我可以在Clojure中进行确定性的随机播放吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14836414/

相关文章:

python - 如何检查列表中的邻接关系,然后修复 python 中的邻接关系

python - 为什么我在第二次运行中直接得到相同的结果而不在Python中运行随机函数?

java - 需要一个快速的 Java beta 分布随机数生成器

cuda - 从 CUDA 中的高斯分布生成随机数

concurrency - Clojure:并行计算产生的数据访问速度似乎要慢得多

clojure - 如何改进这个 Clojure 组件+异步示例?

python - 在 Python 中不重复输出的排列

c++ - 产生超几何分布的随机变量

clojure - 在单独的 Clojure 命名空间中调用函数

c++ - 下一个排列定义