将方案翻译成Java

时间:2019-07-19 21:02:32

标签: java scheme lisp sicp code-translation

在阅读SICP期间,我鼓励练习2.32。

  

我们可以将集合表示为不同元素的列表,并且我们可以   将列表中所有子集的列表表示为列表列表。对于   例如,如果集合为(1 2 3 4),则所有子集的集合为(() (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))。完成以下的定义   生成一组子集并给出清晰结果的过程   解释为什么起作用:

(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))

我可以使用模式来实现,但是之后我想知道:“如何使用Java?”。我考虑了一下,因为如果我们在每个递归中都得到前一个的子列表,我不明白为什么它应该起作用。

我当然可以用其他方式解决它。 例如,使用这种方法:所有可能的组合2 ^​​ N-1,在我们的例子中是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)

我重写了一些与Java类似的方案代码

(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))

我写了我的Java实现

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()))));
    }

}

在Java中,我有一个空列表(我将Set更改为List以便不加任何技巧地获得索引0)。正如我之前提到的,我理解了为什么我的Java返回空列表,但是我不理解如何修复行为与方案匹配的Java代码。

1 个答案:

答案 0 :(得分:2)

您的基本情况是错误的。方案表达式conda config --append envs_dirs "/path to my home directory/my profile/.conda/envs" mkdir -p "/path to my home directory/my profile/.conda/pkgs" conda config --append pkgs_dirs "/path to my home directory/my profile/.conda/pkgs" 不会求值为空列表:它会求值为一个元素列表,其元素为空列表。在Java中,您已将(list '())写为基本情况,这是一个空列表。而是使用类似new ArrayList<>()的东西。