Генерация двоичных чисел из n цифр в clojure

Я хотел бы генерировать двоичные числа n цифры от 0 до 2^n-1. Например, 3 цифры, "000", "001", "010", ..., "111" (от 0 до 7 в десятичной системе). Как я должен использовать java.lang.Integer.toBinaryString() метод и добавьте нули, если это необходимо, например:

(defn pad-zero [s n]
  (str (reduce str (repeat (- n (count s)) "0")) s))

(defn binary-permutation [n]
  (map (fn [s] (pad-zero s n))
       (map #(Integer/toBinaryString %) (range 0 (Math/pow 2 n)))))

С помощью этого кода я могу генерировать то, что хочу. Для 3 цифр:

(binary-permutation 3)
=> ("000" "001" "010" "011" "100" "101" "110" "111")

но эти коды выглядят немного многословен. Есть ли какие-либо способы лучше или более clojure способ сделать это?

2 ответов


вы можете упростить форматирование с помощью cl-format С в Clojure.pprint:

(defn binary-permutation [n]
  (map (partial cl-format nil "~v,'0B" n) (range 0 (Math/pow 2 n))))

Вам также может быть интересно узнать, что (Math/pow 2 n) эквивалентно (bit-shift-left 1 n).

другой способ выразить это было бы в термине выбор С в Clojure.математика.комбинаторика:

(defn binary-permutation [n]
  (map (partial apply str) (selections [0 1] n)))

(defn binary-permutation [n]
  (for [x (range (Math/pow 2 n))]
    (apply str (reverse (take n (map #(bit-and 1 %) (iterate #(bit-shift-right % 1) x)))))))

(defn pad-zero [s n]
  (apply str (take-last n (concat (repeat n ) s))))