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