如何使用未分配给自己的元素进行随机排列

时间:2015-01-14 23:12:07

标签: clojure

如何编写一个带有名称列表并分配每个名称的函数 命名另一个名称,但名称不能相同。

这是我走了多远:

(def people
    '("Peter" "Steve" "Mikel" "Andrea" "Hans" "Oliver" "Greg"))

(defn assign-people []
    (let [perm (map hash-map people  (shuffle people))]
        perm))

此函数产生例如:

({Peter Hans} {Steve Mikel} {Mikel Andrea} {Andrea Greg} {Hans Steve} {Oliver Oliver} {Greg Peter})

如何防止将名称分配给自己?

编辑:还应注意,没有名称被分配两次或更多次但只分配一次

3 个答案:

答案 0 :(得分:4)

可能是

(let [rand (shuffle people)
      second (rest (cycle rand))
      result (map vector rand second)]
    result)

它的作用 - 只是生成一个随机序列,然后循环自身并移动1.因此对于长度为>的每个列表。 1它保证元素不匹配。

结果是一个矢量列表,但不确定它是否适合您的任务。如果是 - 您肯定可以将结果形状更改为您想要的任何内容。

例如,要获取哈希映射列表:

(let [rand (shuffle people)
      second (rest (cycle rand))
      result (map hash-map rand second)]
    result)

答案 1 :(得分:1)

我们可以保留shuffle,直到我们得到没有匹配的答案:

(defn derange [s]
  (loop []
    (let [cand (shuffle s)]
      (if (not-any? identity (map = cand s))
        cand
        (recur)))))

(derange people)
;["Hans" "Greg" "Andrea" "Peter" "Steve" "Mikel" "Oliver"] ; for example

使用相等的值替换值不会令人满意。如果我们想要一个随机排列,无论它是否改变每个值,我们都可以解开索引:

(defn derange [s]
  (let [v (vec s), nos (-> s count range vec)]
    (loop []
      (let [cand (shuffle nos)]
        (if (not-any? identity (map = cand nos))
          (map v cand)
          (recur))))))

(derange (repeat 5 \a))
;(\a \a \a \a \a)

答案 2 :(得分:0)

鉴于n是人数,即:n = (count people)

(->> (cycle people) (partition 2) (take n))

如果您需要将对存储在哈希映射中,则可以在获取后添加(map #(apply hash-map %))。如果你每次都需要一个随机的结果,你可以先给人们洗牌:

(->> (shuffle people) cycle (partition 2) (take n))