Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by

I have a task to create a function which gives powerset of a list.

Output of the list (1 2 3) should be this:

1
2
3
1 2
1 3
2 3
1 2 3
I tried this helper function

(defn print-powerset-helper [lst] (if(not(empty? lst)) (do (println(first lst)) (print-lst (rest lst)))))
which gives me

1
2
3
nil
this output.

I also tired this fucntion:

(defn print-powerset [lst] (if (not (empty? lst)) (do (apply println lst (print-lst lst)))))
output:

1
2
3
(1 2 3)
nil
I want to get rid of parenthesis and also don't understand how to print the middle part of the output. 1 2 1 3 2 3 , this part.

Please any kind of help will be good. Thank you!

2 Answers

+1 vote
by

The powerset is a math problem/solution in set theory.
If you understand the problem and then the solution, you can write out the solution in any language.

See: https://en.wikipedia.org/wiki/Power_set

For solutions to these kind of issues I normally search for Java libraries, 99% of the time there already exist something out there that you can just use, and its been debugged and optimized sufficiently.

https://guava.dev/releases/20.0/api/docs/com/google/common/collect/Sets.html#powerSet-java.util.Set-

If you want to see another Java solution you can look at:
https://www.geeksforgeeks.org/finding-all-subsets-of-a-given-set-in-java/

For a pure clojure solution see:
You could use: https://github.com/clojure/math.combinatorics/

 (require '[clojure.math.combinatorics :as combo])
 (combo/subsets [1 2 3])
 >> (() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3))

The clojure solution in combinatorics is closer to that of the python one in wikipedia and uses combinations to generate the subsets.

https://github.com/clojure/math.combinatorics/blob/master/src/main/clojure/clojure/math/combinatorics.cljc#L218

The java solution is pretty optimized by exploiting the fact that the different combinations can be represented as binary numbers.

by
To print out the values you can use string  join and a doseq

  (require '[clojure.math.combinatorics :as combo])
  (require '[clojure.string :as s])

  (doseq [l (combo/subsets [1 2 3])]
      (println (s/join ",", l)))


  If you want to remove the empty set, use  a filter.

  (doseq [l (filter (complement empty?)  
                                      (combo/subsets [1 2 3]))]
       (println (s/join ",", l)))
0 votes
by
by
Nice. The implementation in  the second answer blows my mind: https://gist.github.com/anonymous/796299
...