Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 有没有更好的方法来实现这个算法来返回一个单词的所有字母顺序组合的列表?_Clojure - Fatal编程技术网

Clojure 有没有更好的方法来实现这个算法来返回一个单词的所有字母顺序组合的列表?

Clojure 有没有更好的方法来实现这个算法来返回一个单词的所有字母顺序组合的列表?,clojure,Clojure,我记得在过去写过一个Python程序,它也做过同样的事情。我记得我认为这个算法很聪明,但现在试图在Clojure中从内存实现它,我遇到了一些问题 我对Clojure很陌生,所以我知道我可能没有用最好的方式来做这件事 下面我使用单词“herps”作为测试,它应该会返回一个单词所有可能组合的列表。我终于找到了正确的组合,但它们是嵌套的,我想要一个简单的单词列表。我认为这是因为for返回了一个懒惰的seq,但我不知道如何绕过它 (ns combos.core (:gen-class)) (use

我记得在过去写过一个Python程序,它也做过同样的事情。我记得我认为这个算法很聪明,但现在试图在Clojure中从内存实现它,我遇到了一些问题

我对Clojure很陌生,所以我知道我可能没有用最好的方式来做这件事

下面我使用单词“herps”作为测试,它应该会返回一个单词所有可能组合的列表。我终于找到了正确的组合,但它们是嵌套的,我想要一个简单的单词列表。我认为这是因为for返回了一个懒惰的
seq
,但我不知道如何绕过它

(ns combos.core
  (:gen-class))
(use '[clojure.string :only [join]])

(defn rmletter [in letter]
    (join (remove #(= letter %) in)))

(defn combo [total in]
    (if (= (count in) 1)
        (concat total (list in))
        (for [item in] 
            (do
            (if (= (count in) 5) (print "top: "))
            (combo (concat total (list item)) (rmletter in item)))
        )))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  ;; work around dangerous default behaviour in Clojure
  (alter-var-root #'*read-eval* (constantly false))
  (doseq [item (combo nil "herps")] (print "item:")(println item))
  (println "Hello, World!"))
以下是输出:

top: item:((((h e r p s) (h e r s p)) ((h e p r s) (h e p s r)) ((h e s r p) (h
e s p r))) (((h r e p s) (h r e s p)) ((h r p e s) (h r p s e)) ((h r s e p) (h
r s p e))) (((h p e r s) (h p e s r)) ((h p r e s) (h p r s e)) ((h p s e r) (h
p s r e))) (((h s e r p) (h s e p r)) ((h s r e p) (h s r p e)) ((h s p e r) (h
s p r e))))
top: item:((((e h r p s) (e h r s p)) ((e h p r s) (e h p s r)) ((e h s r p) (e
h s p r))) (((e r h p s) (e r h s p)) ((e r p h s) (e r p s h)) ((e r s h p) (e
r s p h))) (((e p h r s) (e p h s r)) ((e p r h s) (e p r s h)) ((e p s h r) (e
p s r h))) (((e s h r p) (e s h p r)) ((e s r h p) (e s r p h)) ((e s p h r) (e
s p r h))))
top: item:((((r h e p s) (r h e s p)) ((r h p e s) (r h p s e)) ((r h s e p) (r
h s p e))) (((r e h p s) (r e h s p)) ((r e p h s) (r e p s h)) ((r e s h p) (r
e s p h))) (((r p h e s) (r p h s e)) ((r p e h s) (r p e s h)) ((r p s h e) (r
p s e h))) (((r s h e p) (r s h p e)) ((r s e h p) (r s e p h)) ((r s p h e) (r
s p e h))))
top: item:((((p h e r s) (p h e s r)) ((p h r e s) (p h r s e)) ((p h s e r) (p
h s r e))) (((p e h r s) (p e h s r)) ((p e r h s) (p e r s h)) ((p e s h r) (p
e s r h))) (((p r h e s) (p r h s e)) ((p r e h s) (p r e s h)) ((p r s h e) (p
r s e h))) (((p s h e r) (p s h r e)) ((p s e h r) (p s e r h)) ((p s r h e) (p
s r e h))))
top: item:((((s h e r p) (s h e p r)) ((s h r e p) (s h r p e)) ((s h p e r) (s
h p r e))) (((s e h r p) (s e h p r)) ((s e r h p) (s e r p h)) ((s e p h r) (s
e p r h))) (((s r h e p) (s r h p e)) ((s r e h p) (s r e p h)) ((s r p h e) (s
r p e h))) (((s p h e r) (s p h r e)) ((s p e h r) (s p e r h)) ((s p r h e) (s
p r e h))))
Hello, World!

我想你需要在你的答案中加入一个
应用concat

正确生成排列的完整答案并不严格,如果它满足您的需要,请使用它。不过,值得描述一个简单的算法:

(defn perms [v]
  (cond (= 1 (count v)) v                        ; one permutation is it's self 
        (= 2 (count v)) [[(second v) (first v)]  ; two items is [[ab][b a]]
                         [(first v) (second v)]]
        :default
        (apply concat                   
               (for [i (range (count v))]        ; take the first item     
                 (->> (assoc v i (v 0))          ; add it in each position 
                      (#(subvec % 1))            ; find the permutations of 
                      perms                      ; the rest of each of them 
                      (mapv #(conj % (nth v i)))))))) ; then stick the 
                                                 ; one that was assoced back
                                                 ; onto the start of each of them 
有更好的方法来计算这个问题,这个简单的递归方法给我的印象是,它是解决这个问题的一种非常正确的方法。重要的一点是对works的
assoc
调用,因为它是持久的,不会破坏其他递归分支使用的版本

hello.exp> (pprint (perms (vec "1234")))                                                                                                                                           
([\4 \3 \2 \1]                                                                                                                                                                     
 [\3 \4 \2 \1]                                                                                                                                                                     
 [\4 \2 \3 \1]                                                                                                                                                                     
 [\2 \4 \3 \1]                                                                                                                                                                     
 [\2 \3 \4 \1]                                                                                                                                                                     
 [\3 \2 \4 \1]                                                                                                                                                                     
 [\4 \3 \1 \2]                                                                                                                                                                     
 [\3 \4 \1 \2]                                                                                                                                                                     
 [\4 \1 \3 \2]                                                                                                                                                                     
 [\1 \4 \3 \2]                                                                                                                                                                     
 [\1 \3 \4 \2]                                                                                                                                                                     
 [\3 \1 \4 \2]                                                                                                                                                                     
 [\4 \1 \2 \3]                                                                                                                                                                     
 [\1 \4 \2 \3]                                                                                                                                                                     
 [\4 \2 \1 \3]                                                                                                                                                                     
 [\2 \4 \1 \3]                                                                                                                                                                     
 [\2 \1 \4 \3]                                                                                                                                                                     
 [\1 \2 \4 \3]                                                                                                                                                                     
 [\1 \3 \2 \4]                                                                                                                                                                     
 [\3 \1 \2 \4]                                                                                                                                                                     
 [\1 \2 \3 \4]                                                                                                                                                                     
 [\2 \1 \3 \4]                                                                                                                                                                     
 [\2 \3 \1 \4]                                                                                                                                                                     
 [\3 \2 \1 \4])                                                                                                                                                                    
nil                                                                                                                                                                                
hello.exp> (count (perms (vec "hello")))  
120

实际上,使用组合数学库中的lazy perm来避免像这个版本那样破坏堆栈。

我喜欢这些小难题,忍不住要打高尔夫球:

(defn perms1 [xs] (if-not (next xs) [xs] (->> [[] xs] (iterate (fn [[a [x & b]]] ;; seq of all splits of xs [(conj a x) b])) (take-while second) (mapcat (fn [[a [x & b]]] (map #(cons x %) ;; cons split point onto each comb of the rest (perms1 (concat a b)))))))) (defn perms1[xs] (如果不是(下一个xs) [xs] (->[]xs] (迭代(fn[[a[x&b]];;x的所有拆分的顺序) [(联合a x)b])) (稍等片刻) (mapcat(fn[[a[x&b]]] (映射#(cons x%);cons拆分点到其余的每个梳子上 (perms1(concat a b(()())()))) 注意:perms1通过在输出序列中生成重复的组合来处理输入集合中的重复项。如果我们确定输入中没有DUP,我们可以使用集合来保存集合中的其余项,从而稍微收紧代码:

(defn perms2 [xs] (if-not (next xs) [xs] (mapcat (fn [x] (map cons (repeat x) (perms2 (disj (set xs) x)))) xs))) (defn perms2[xs] (如果不是(下一个xs) [xs] (mapcat(fn[x] (地图) (重复x) (perms2(disj(set xs)x))) (xs)) 原始解决方案中的嵌套seq是因为您的组合总是返回seq,for总是返回其主体返回的seq,因此您最终得到了seq的seq,嵌套到递归的深度。请注意我的解决方案如何使用mapcat而不是for来避免此问题。对for的结果调用(应用concat…)将是另一种使结果平坦化的方法。

以下是我的解决方案

(defn but-nth [s i]
  [(get s i) (into [] (concat (take i s) (take-last (dec (- (count s) i)) s)))])

(defn combs [sofar r]
  (if (empty? r)
    sofar
    (for [[c z] (map (partial but-nth r) (range (count r)))]
      (combs (conj sofar c) z))))

(defn r-combs [s]
  (map (fn [x] (apply str x)) (partition (count s) (flatten (combs [] (vec s))))))

(r-combs "herps")

支票及其功能。看起来这正是您想要的。Re:
-main
read
中的注释不应用于反序列化从不受信任的源获取的数据。为此,在clojure>=1.5中使用
clojure.edn/read
,在早期版本中使用
tools.reader
contrib库中的edn读取器(它位于
clojure.tools.reader.edn
命名空间中)。将
*read eval*
设置为
false
在Clojure<1.5中是不够的安全预防措施,甚至在Clojure>=1.5中,“true”阅读器用于读取代码,而不是任意数据,可能是后一种应用程序中不安全的工具。只是为了好玩:
(取120(不同的(重复地)(shuffle(seq“ehprs”))))