【问题标题】:Reaching the result then returns to the initial state达到结果然后返回初始状态
【发布时间】:2016-09-29 16:23:48
【问题描述】:

所以我正在学习prolog。

我要做的就是改变元素的顺序并得到新的列表作为结果。

在跟踪解决方案时,我得到了正确的答案,但是一旦我达到基本情况,Prolog 开始再次清空列表并返回并清空列表。

代码:

accRev([], [], _) :- !.
accRev([], A, R) :- accRev(A, [], R), !.
accRev([H, H2 |T], A, R):-
  append(R, [H], R1),
  append(A, [H2], A1),
  accRev(T, A1, R1), !.
accRev([H], A, R):-
  append(R, [H], R1),
  accRev(A, [], R1), !.

accRevT([], [], _) :- !.
accRevT([], A, R) :- accRev(A, [], R), !.
accRevT([H, H2 |T], A, R):-
  append(R, [H], R1),
  append(A, [H2], A1),
  accRevT(T, [H2 | A], [H | R]), !.
accRevT([H], A, R):-
  append(R, [H], R1),
  accRevT(A, [], [H | R]), !.

轨迹图像

注意它是如何达到 accRev([], [], [1, 3, 2, 4]) 的(这就是我希望 R 变成的样子,R = [1, 3, 2, 4])

那怎么了?

【问题讨论】:

  • this answer。当你使用累加器时,你应该在你的递归结束子句中有一个匿名变量_。该子句通常读作foo([], Acc, Acc).,而不是foo([], [], _).
  • 您的代码的另一个主要问题:削减太多。你真的知道他们每个人是做什么的吗?您知道将它们排除在外是否会改变程序吗?
  • 你到底想要什么作为输出——你的程序的目的是什么,因为“改变元素的顺序”不是很清楚......

标签: list prolog


【解决方案1】:

如果你能正确理解你想要做什么,你可以写:

  accRev([],[]).
  accRev([X|Y], Lout):-
    split_list([X|Y],Z1),
    split_list(Y,Z2),
    accRev(Z2,Z3),
    append(Z1,Z3,Lout).


split_list([],[]).
split_list([X|[]], [X]).
split_list([X,_|T], [X|R]):-split_list(T,R).

例子:

?- accRev([1,2,3,4],R).
R = [1, 3, 2, 4] ;
false.

在您的解决方案中,我认为某些问题是由于使用了太多的削减和鲍里斯所写的accRev([], [], _) 而引起的,而且我认为您不需要中间列表,因为例如子句:

accRev([], [], _) :- !.
accRev([], A, R) :- accRev(A, [], R), !.

会导致问题,因为如果第一个列表是空列表,则两个子句都匹配。

【讨论】:

    猜你喜欢
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 2014-12-21
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多