【问题标题】:Prolog possible removal of elements in a listProlog 可能删除列表中的元素
【发布时间】:2016-02-12 15:11:49
【问题描述】:

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

例如,如果我有一个列表 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]

为此,我已经编写了 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]).

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

【问题讨论】:

  • 我无法理解问题陈述。 “从列表中的任何单个元素中删除任何数字”是什么意思?有时,您正在从列表中删除一个元素(更改元素总数),有时您似乎正在从一个元素中减去(因此元素总数保持不变)。哪一个?还是两者兼而有之?
  • 如何在删除元素 frim [1, 2, 3] 时得到例如[1, 1, 2]
  • 对不起,混淆了,实际上是从列表中减去一个元素,如果结果为0,则将其丢弃。例如,X = [1,2],Y可以是[ 1-1, 2],在这种情况下,1-1 = 0,所以结果是[2]。第二种情况是[1, 2-1],所以结果是[1,1]。第三种情况是[1,2-2],同样,2-2 =0,所以结果是[1]。希望这是有道理的。
  • @lurker 这实际上是我接下来需要做的事情,但我不知道该怎么做。
  • 这个问题现在已经完全改变了。你最初的问题是如何删除一个元素,你得到了两个答案。现在你改变了问题,引入了两个额外的答案,问题变成了,“有没有更好的方法来做到这一点?”这完全改变了问题并使给出的答案无效。这应该在一个新问题中提出,而不是完全改变这个问题。

标签: list search prolog


【解决方案1】:

你必须:

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

例如:

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) 时,它不会出现在第二个列表中。

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

【讨论】:

  • 所以“数字”实际上是指非负整数?
  • 第二个代码的质量如何?你的看起来好多了。
  • @Boris:我认为 OP 的意思是非负整数
  • 但是这里有个问题。对于我的代码,最后我不会得到“假”。您将如何防止这种情况发生??
  • @user3390652:cmets 不是问更多问题的正确地方(这里很难显示代码)。对于扩展问题,一个简单的解决方案是保留remove 原样,然后创建另一个过程remove2,这几乎相同,但在第1 和第2 条中,将head 的第二个参数中的Tail 更改为NTail并在两个子句的最后一行添加对remove(Tail, NTail) 的调用,即:remove2([N|Tail], [NX|NTail]):- succ(N1, N), between(1, N1, NX), remove(Tail, NTail).remove2([_|Tail], NTail):- remove(Tail, NTail).
【解决方案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
    ).

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    相关资源
    最近更新 更多