Clojure:编写一个Clojure函数,返回长度为n的所有2 ^ n位字符串的列表

时间:2014-03-10 01:40:39

标签: string recursion clojure

我想编写一个名为(nbits n)的Clojure函数,它返回长度为n的所有2 ^ n位字符串的列表。

我的预期输出是:

user=> (nbits -2)
()

user=> (nbits 0)
()

user=> (nbits 1)
((0) (1))

user=> (nbits 2)
((0 0) (0 1) (1 0) (1 1))

user=> (nbits 3)
((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))

这是我的尝试:

(defn add0 [seq] 
  (cond (empty? seq) 'nil
        (and (seq? seq) (> (count seq) 0)) 
          (cons (cons '0 (first seq)) (add0 (rest seq)))))

(defn add1 [seq]
  (cond (empty? seq) 'nil
        (and (seq? seq) (> (count seq) 0)) 
          (cons (cons '1 (first seq)) (add1 (rest seq)))))

(defn nbits [n]
  (cond (number? n) 
          (cond (< n 1) '()
                (= n 1) '((0) (1))
                (> n 1) 
                  (list (add0 (nbits (- n 1))) (add1 (nbits (- n 1))))) 
        :else 'nil))

但输出不对。我哪里做错了?我不知道如何解决它。

3 个答案:

答案 0 :(得分:2)

您也可以使用math.combinatorics库执行此操作(懒惰和迭代):

user=> (defn nbits [n] 
         (if (pos? n) 
           (clojure.math.combinatorics/selections [0 1] n) 
           '()))
#'user/nbits
user=> (nbits 0)
()
user=> (nbits 1)
((0) (1))
user=> (nbits 2)
((0 0) (0 1) (1 0) (1 1))
user=> (nbits 3)
((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))

这个版本的优点是可以利用迭代来避免使用堆栈(我在机器上使用原始版本时n = 14)。

答案 1 :(得分:1)

您的问题的简短回答是将list替换为concat中的nbits。您的add0add1都会返回“位”列表的列表,因此创建这两个列表列表会增加一个列表嵌套级别。您想要连接add0add1的结果。

答案 2 :(得分:1)

另一种方法是迭代数字并将每个数字转换为序列而不是重新实现添加。

(defn nbits [n] 
  (for [m (range (Math/pow 2 n))]
    (map #(if (bit-test m %) 1 0) (range (dec n) -1 -1))))