Вы можете создать подмножество множества, как это:
(defn subsets [s]
(if (seq s)
(let [f (first s), srs (subsets (disj s f))]
(concat srs (map #(conj % f) srs)))
(list #{})))
Идея заключается в том, чтобы выбрать элемент из множества s
: первого, f
, будет делать. Затем мы рекурсивно находим подмножества всего остального, srs
. srs
содержит все подмножества без f
. Добавляя f
к каждому из них, мы получаем все подмножества с f
. И вместе, это жребий. Наконец, если мы не можем выбрать элемент, потому что его нет, единственное подмножество - пустое.
Осталось только отфильтровать все подмножества, которые суммируются с n
. Функцией для тестирования является
(fn [s] (= n (reduce + s)))
Не стоит называть.
Сведя вместе, функция, которую мы хотим
(defn subsets-summing-to [s n]
(filter
(fn [xs] (= n (reduce + xs)))
(subsets s)))
Примечания
- Поскольку ответ последовательность множеств, мы можем сделать его ленивее путем изменения
concat
в lazy-cat
. map
ленив в любом случае.
- Возможно, мы создаем множество наборов, но помним, что они совместно используют хранилище: стоимость пространства для хранения другого набора, отличающегося одним элементом, является (почти) постоянной.
- Пустые суммы сумм равны нулю в арифметике Clojure.
Это вопрос интервью? Я слышал, что этот вопрос задают довольно часто в интервью Clojure в эти дни. – DNNX
@DNNX это связано с проблемой 4clojure.com «Sum Some Set Subsets» http://www.4clojure.com/problem/131 – tangrammer
нет, а не интервью ... – szymanowski