0

I'm new to clojure, attempting to write a function (all-bit-seqs n) that generates all bit strings of length n as a list. So if I were to call (all-bit-seqs 2), it would output ((0 0) (0 1) (1 0) (1 1)) in any order. However, I am getting a NullPointerException when I call the helper function rest-bit-seqs, and I can't figure out why. My code is as follows, any help would be appreciated.

(defn not-bit [x]
    (* -1 (- x 1))
)

(defn inc-bit-seq [x]
    (cond
        (= 0 (not-bit (first x))) (cons 0 (inc-bit-seq (rest x)))
        :else (cons 1 (rest x))
    )
)

(defn pow [x, y]
    (cond
        (not= y 0) (* x (pow x (- y 1)))
        :else 1
    )
)

(defn rest-bit-seqs [n, x, lst]
    (cond
        (not= x (pow 2 n)) (cons lst (rest-bit-seqs n (+ 1 x) (inc-bit-seq lst)))
        :else '()
    )
)

(defn zero-seq [n]
    (cond
        (= n 0) '()
        :else (cons 0 (zero-seq (- n 1)))
    )
)

(defn all-bit-seqs [n]
    (rest-bit-seqs n 0 (zero-seq n))
)
1
  • 1
    BTW, in the future try to find the smallest possible amount of code that replicates your problem. There shouldn't have been any need here for any functions other than inc-bit-seq and not-bit, and of course an example calling them with appropriate data. See also stackoverflow.com/help/mcve Commented Feb 21, 2016 at 1:10

2 Answers 2

2

that is because you don't handle the case of an empty sequence here:

(defn inc-bit-seq [x]
    (cond
        (= 0 (not-bit (first x))) (cons 0 (inc-bit-seq (rest x)))
        :else (cons 1 (rest x))
    )
)

so at one point you pass (first x) (which is nil for an empty seq) to not-bit.

the following fix solves this:

(defn inc-bit-seq [x]
  (when (seq x)
    (cond
      (= 0 (not-bit (first x))) (cons 0 (inc-bit-seq (rest x)))
      :else (cons 1 (rest x))
      ))
)

in repl:

user> (all-bit-seqs 2)
((0 0) (1 0) (0 1) (1 1))

the other things that are totally weird here, is your choice of cond instead of simple if, and uncommon formatting. I would consider rewriting the code this way:

(defn not-bit [x]
  (* -1 (- x 1)))

(defn inc-bit-seq [x]
  (when (seq x)
    (if (zero? (not-bit (first x)))
      (cons 0 (inc-bit-seq (rest x)))
      (cons 1 (rest x)))))

(defn pow [x, y]
  (if-not (zero? y)
    (* x (pow x (- y 1)))
    1))

(defn rest-bit-seqs [n, x, lst]
  (when-not (== x (pow 2 n))
    (cons lst (rest-bit-seqs n (+ 1 x) (inc-bit-seq lst)))))

(defn zero-seq [n]
  (when-not (zero? n)
    (cons 0 (zero-seq (- n 1)))))

(defn all-bit-seqs [n]
  (rest-bit-seqs n 0 (zero-seq n)))

(it's about style, haven't looked at overall code correctness)

Sign up to request clarification or add additional context in comments.

Comments

1

Your error is here:

(= 0 (not-bit (first x)))

If x is empty, (first x) will return nil, so this will happen:

(= 0 (not-bit nil))
(= 0 (* -1 (- nil 1))

When you try to evaluate (- nil 1), you'll get a NullPointerException.

The quick-and-dirty way to fix the problem is to get rid of not-bit and replace that condition with

(= 1 (first x))

However, there are much shorter/simpler ways to solve this problem. Here's one way:

(defn inc-bit-seq [[head & tail]]
  (if (zero? head)
    (cons 1 tail)
    (cons 0 (inc-bit-seq tail))))

(defn all-bit-seqs [n]
  (take (bit-shift-left 1 n)
        (iterate inc-bit-seq (repeat n 0))))

Another way would be to use strings:

(defn pad-first [n x xs]
  (concat (repeat (- n (count xs)) x) xs))

(defn all-bit-seqs [n]
  (map (comp (partial pad-first n 0)
             (partial map #(Character/getNumericValue %))
             #(Long/toBinaryString %))
       (range (bit-shift-left 1 n))))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.