Prolog可能删除列表中的元素

时间:2015-11-11 13:55:09

标签: list search prolog

我被要求尝试搜索所有可能的结果,从列表中的任何单个元素中删除任何数字。

例如,如果我有一个列表X = [1,2,3]

remove(X, Y)

我的结果将是:

Y = [2,3]
Y = [1,1,3]
Y = [1,3]
Y = [1,2,2]
Y = [1,2,1]
Y = [1,2]

为此,我已经写了两个解决方案,但我真的不知道我的解决方案的缺点是什么。我的教授一直告诉我,有更好的办法。

我的第一种方法:

test(S1, S2):-
    length(S1, L),
    M is L -1,
    between(0, M, N),
    remove(S1, S2, N).
remove([H|T], [H2|T2], Heap):-
    (
        Heap>0->
        H2 = H,
        remove(T, T2, Heap-1);
        between(1, H, N),
        H2 is H - N,
        T2 = T
    ).

我的第二种方法:

remove1([H|T], [H|TY]):-
    not(T=[]),
    remove1(T, TY).
remove1([H|T], S2):-
    between(1, H, X),
    HY is H - X,
    (   HY = 0-> S2 = T; S2=[HY|T]).

这两种方法都给出了相同的结果,但我确实想知道如何做得更好。有人会介意给我一些建议吗?

2 个答案:

答案 0 :(得分:2)

你必须:

  • 从列表中选择一个项目(编号)
  • 使用小于所选项目的数字替换所选项目
  • 或者完全删除所选项目

例如:

remove([N|Tail], [NX|Tail]):-
  succ(N1, N),
  between(1, N1, NX).
remove([_|Tail], Tail).
remove([N|Tail], [N|NTail]):-
  remove(Tail, NTail).

第一个子句选择列表中的第一个项目,并用小于项目的数字替换该项目。

第二个子句从列表中删除该项目(如示例所示,当您将N减去所选项目(N)时,它不会出现在第二个列表中。

第三个子句应用递归,将头部项保持原样,并将该过程应用于剩余列表。

答案 1 :(得分:2)

这是使用append/3的另一种解决方案。我认为@ gusbro的答案更优雅和/或更有效率。但它是另一种选择:

reduce(L, R) :-
    append(L1, [X|L2], L),
    (   X1 is X - 1,              % some element varies 1 to X-1
        between(1, X1, Y),
        append(L1, [Y|L2], R)
    ;   append(L1, L2, R)         % or the element is just removed
    ).