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

How do I make a random permutation with elements not assigned to themself

我如何编写一个函数,它接受一个名称列表并为每个名称赋值 命名另一个不能相同的名称。

这是我得到的结果:

(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})

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

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

可能是

(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)

假设n是人数,即:n = (count people):

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

如果您需要将这些对存储在哈希图中,您可以在 take 之后添加 (map #(apply hash-map %))。如果你每次都需要一个随机结果,你可以先洗牌:

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

我们可以继续 shuffleing 直到我们得到没有匹配的答案:

(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)