如何使用递归

时间:2017-10-13 12:59:12

标签: list prolog duplicates

我想删除列表A和B中的每个第n个元素,它们彼此不对应的第n个元素。例如:我的列表A包含[1,2,3,4,5],列表B包含[1,2,2,4,7]。结果应该是包含C的列表[3,5]和包含D的列表[2,7]。我想出了这段小代码,但它还没有正常工作。

without_doubles([], [], [_], [_]).
without_doubles([H|T1], [H|T2], C, D):-
    without_doubles(T1, T2, C, D).
without_doubles([H1|T1], [H2|T2], [H1|C], [H2|D]):-
    without_doubles(T1, T2, C, D).

而不是[3,5][2,7],我得到[3,5,_G2442][2,7,_G2445]。我知道它可能很容易修复,但我似乎无法弄明白。谢谢你提前帮助我!

2 个答案:

答案 0 :(得分:4)

你的第一条规则应该是:

without_doubles([], [], [], []).

您之前遇到的两个匿名变量_是导致问题的原因。

但是您的代码存在第二个问题:

?- without_doubles([1,2,3,4,5],[1,2,2,4,7],L,R).
L = [3, 5],
R = [2, 7] ;
L = [3, 4, 5],
R = [2, 4, 7] ;
L = [2, 3, 5],
R = [2, 2, 7] ;
L = [2, 3, 4, 5],
R = [2, 2, 4, 7] ;
L = [1, 3, 5],
R = [1, 2, 7] ;
L = [1, 3, 4, 5],
R = [1, 2, 4, 7] ;
L = [1, 2, 3, 5],
R = [1, 2, 2, 7] ;
L = [1, 2, 3, 4, 5],
R = [1, 2, 2, 4, 7].

显然我们只想要第一个结果,而不是其他结果。我们得到其他内容的原因是因为您在上一条规则中没有说明H1H2应该是不同的。这意味着当Prolog可以应用第二条规则时,它也可以应用最后一条规则,从而创建所有这些选择点。

您可以使用H1明确说明上一条规则中的H2dif/2必须不同,以解决此问题:

without_doubles([H1|T1], [H2|T2], [H1|C], [H2|D]):-
    dif(H1, H2),
    without_doubles(T1, T2, C, D).

现在我们有:

?- without_doubles([1,2,3,4,5],[1,2,2,4,7],L,R).
L = [3, 5],
R = [2, 7] ;
false.

答案 1 :(得分:3)

您的代码存在两个问题:

  1. basecase将singleton列表指定为第三个和第四个参数,而这些列表应为空列表;
  2. 没有什么阻止你回溯第二个条款,因此采取第三个条款。
  3. 您可以按照以下方式解决此问题:

    %% no [_], but []
    without_doubles([], [], [], []).
    without_doubles([H|T1], [H|T2], C, D):-
        without_doubles(T1, T2, C, D).
    %% guard the fact that H1 and H2 are different
    without_doubles([H1|T1], [H2|T2], [H1|C], [H2|D]):-
        dif(H1,H2),
        without_doubles(T1, T2, C, D).