如何在Clojure中真正洗牌序列?

如何在Clojure中真正洗牌序列?,clojure,shuffle,Clojure,Shuffle,但若你们把“测试”放进去,有时你们可以把“测试”拿回来 如何修改代码以确保输出永远不等于输入 我觉得很尴尬,我可以用Python轻松解决它,但Clojure对我来说太不一样了 多谢各位 我想我们现在可以结束这个话题了。。。实际上,循环是我所需要的全部…您可以使用。当混洗的字母与原始字母相同时,重复出现返回到循环的开始处: (defn shuffle-letters [word] (let [letters (clojure.string/split word #"")

但若你们把“测试”放进去,有时你们可以把“测试”拿回来

如何修改代码以确保输出永远不等于输入

我觉得很尴尬,我可以用Python轻松解决它,但Clojure对我来说太不一样了

多谢各位

我想我们现在可以结束这个话题了。。。实际上,
循环
是我所需要的全部…

您可以使用。当混洗的字母与原始字母相同时,
重复出现
返回到
循环的开始处

(defn shuffle-letters 
  [word]
  (let [letters (clojure.string/split word #"")
        shuffled-letters (shuffle letters)]
  (clojure.string/join "" shuffled-letters)))
有很多方法可以写出来,但我认为这是最简单的。您还可以摆脱
循环
,并使
洗牌字母
本身递归。但这会导致不必要的工作。您还可以使用
let fn
创建一个局部递归函数,但此时,
loop
可能更干净


但需要注意的是:

  • 显然,如果您尝试洗牌像
    “H”
    “HH”
    这样的东西,它将被卡住并永远循环,因为再多的洗牌都不会导致它们不同。您可以提前进行检查,或者在
    循环中添加一个参数来限制它的尝试次数

  • 这实际上会减少你的洗牌随机性。如果不允许它返回原始字符串,则会减少可能的输出量

  • 不需要调用
    split
    。您只需调用字符串:

    (defn shuffle-letters [word]
      (let [letters (clojure.string/split word #"")]
        (loop []  ; Start a loop
          (let [shuffled-letters (shuffle letters)]
            (if (= shuffled-letters letters)  ; Check if they're equal
              (recur)  ; If they're equal, loop and try again
              (clojure.string/join "" shuffled-letters))))))  ; Else, return the joined letters
    
这里是另一种解决方案(使用传感器):


我们基本上创建了一个可能的无序排列的惰性列表,然后我们将第一个无序排列与输入不同。我们还确保输入中至少有2个不同的字符,以免挂起(我们在此处返回
nil
,因为您不希望输入字符串成为可能的结果)。

如果您希望函数返回序列:

(定义我的洗牌[输入]
(当(->输入集计数(>1))
(->)输入
(迭代#(应用str(shuffle(seq%)))
(删除#(=input%'))))
(->“abc”我的洗牌(第5步))
;; => (“acb”“cba”“bca”“acb”“cab”)
(>>“bbb”我的洗牌(第5步))
;; => ()

循环,非常简单。。。事实上,这就是我所需要的。多谢各位<代码>(如果(=(计数(重复数据消除字))1).
应有助于解决“HH”problem@ivitek
loop
通常不是最好的解决方案(像
reduce
这样的函数通常更好),但这是一种更通用的循环方法。练习它很好。如果有疑问,'loop'可能会在需要循环时起作用。@ivitek除非有一个我想不到的极端情况,是的,这应该有助于防止无限循环。
(defn shuffle-letters [word]
  (let [letters (vec word)]
    (loop []
      (let [shuffled-letters (shuffle letters)]
        (if (= shuffled-letters letters)
          (recur)
          (clojure.string/join "" shuffled-letters))))))
 (defn shuffle-strict [s]
  (let [letters (seq s)
        xform (comp (map clojure.string/join)
                 (filter (fn[v] (not= v s))))]
    (when (> (count (into #{} letters)) 1)
      (first (eduction xform (iterate shuffle letters))))))

 (for [_ (range 20)]
         (shuffle-strict "test"))
 ;; => ("etts" "etts" "stte" "etts" "sett" "tste" "tste" "sett" "ttse" "sett" "ttse" "tset" "stte" "ttes" "ttes" "stte" "stte" "etts" "estt" "stet")

(shuffle-strict "t")
;; => nil

(shuffle-strict "ttttt")
;; => nil