During the reading SICP I encouraged with Exercise 2.32.
We can represent a set as a list of distinct elements, and we can represent the set of all subsets of the set as a list of lists. For example, if the set is
(1 2 3 4)
, then the set of all subsets is(() (4) (3) (3 4) (2) (2 4) (2 3) (2 3 4) (1) (1 4) (1 3) (1 3 4) (1 2) (1 2 4) (1 2 3) (1 2 3 4))
. Complete the following definition of a procedure that generates the set of subsets of a set and give a clear explanation of why it works:(define (subsets s) (if (null? s) (list nil) (let ((rest (subsets (cdr s)))) (append rest (map ⟨??⟩ rest)))))
(define (subset s)
(if (null? s)
(list '())
(let ((rest (subset (cdr s))))
(append
rest (map (lambda (x) (cons (car s) x)) rest)
)
)))
(subset '(1 2 3 4))
1 ]=>
;Value 15: (() (4) (3) (3 4) (2) (2 4) (2 3) (2 3 4) (1) (1 4) (1 3) (1 3 4) (1 2) (1 2 4) (1 2 3) (1 2 3 4))
I could do it with schema, but after it I wondered: "How would I can do with java?". I thought about it because I could`t understand why it should work if we got in each recursion a sublist from the previous one.
Of course I can solute it in another way. For instance, with this approach: all possible combinations 2^N-1, for our case this is 2^4-1
number binary result
1 0001 (4)
2 0010 (3)
3 0011 (3,4)
4 0100 (2)
5 0101 (2,4)
6 0110 (2,3)
7 0111 (2,3,4)
8 1000 (1)
9 1001 (1,4)
10 1010 (1,3)
11 1011 (1,3,4)
12 1100 (1,2)
13 1101 (1,2,4)
14 1110 (1,2,3)
15 1111 (1,2,3,4)
I rewrited a little scheme code to similarity with java one
(define (subset s)
(if (null? s)
(list '())
((lambda (rest)
(append rest (map (lambda (x) (cons (car s) x)) rest))
)(subset (cdr s)))
)
)
(subset '(1 2 3))
1 ]=>
;Value 19: (() (4) (3) (3 4) (2) (2 4) (2 3) (2 3 4) (1) (1 4) (1 3) (1 3 4) (1 2) (1 2 4) (1 2 3) (1 2 3 4))
I wrote my java implementation
import java.util.*;
import java.util.function.UnaryOperator;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.*;
public class A {
public static void main(String[] args) {
List<Integer> l = new ArrayList<>(asList(1,2,3));
System.out.println(subset(l));
}
private static List<List<Integer>> subset(final List<Integer> s) {
if (s.isEmpty()) return new ArrayList<>();
final UnaryOperator<List<List<Integer>>> f = (final List<List<Integer>> rest) -> {
final List<List<Integer>> collect = rest.stream()
.map(x -> {
List<Integer> r = new ArrayList<>();
r.add(s.get(0));
r.addAll(x);
return r;
})
.collect(toList());
rest.addAll(collect);
return rest;
};
return f.apply(subset(new ArrayList<>(s.subList(1, s.size()))));
}
}
In java I have the empty list (I changed Set to List in order to get by the index 0 without any tricks). And as I mentioned before I understand why my java returns the empty list, but I don`t understand how to fix my java code that it behavior matches scheme.