Prolog:我新创建的列表在退出递归时变空了?

时间:2015-03-11 00:02:04

标签: recursion prolog

我是prolog的新手,我处于解决一个问题的边缘,但是当我试图退出递归并将列表返回到初始函数时,我遇到了问题。你能帮帮我吗?我整天都在苦苦挣扎。感谢

以下是我构建列表时最终会发生的事情: enter image description here

以下是我的谓词:

depth_first(N, ReturnList) :-
   df_real(2:1, N, [2:1], ReturnList).

df_real(_:NextRankC, Size, Q, ReturnList) :- 
   genInt(Size, Row), 
   Column is NextRankC + 1,
   Rank = Row:Column,
   not(list_attack(Rank, Q)),
   add(Rank, Q, NewList),
   df_real(1:Column, Size, NewList, NewList).
% Recursive Case: Exit when list is full.
df_real(_, N, Q, Newlist) :- length(Q, Length),
   N = Length.

调用谓词: depth_first(4,Q)。 注意:假设genInt/2add/3list_attack/2工作正常,我的问题最终只是删除了我刚刚构建的所有元素并返回了一些变量,它必须返回列表而不是true。

更新当我使用

 df_real(_:NextRankC, Size, Q, NewList) :-
    ...
    df_real(1:Column, Size, NewList, NewList).

跟踪 - 失败,因为NewList现在是一个List而不是要添加到列表中的变量。

enter image description here

1 个答案:

答案 0 :(得分:1)

最终,代码的问题是您需要设置适当的模式来返回列表。 Prolog中的一个常见模式是传入一个通过所有递归传递的变量参数,并最终在终端案例中实例化。该变量最初在第一个子句中设置。

depth_first(N, ReturnList) :-
    df_real(2:1, N, [2:1], ReturnList).

所以这里第一个查询是以第四个参数作为返回答案列表的变量ReturnList启动的。到目前为止,非常好。

df_real(_:NextRankC, Size, Q, ReturnList) :- 
    genInt(Size, Row), 
    Column is NextRankC + 1,
    Rank = Row:Column,
    not(list_attack(Rank, Q)),
    add(Rank, Q, NewList),
    df_real(1:Column, Size, NewList, NewList).

最初,你有_作为第四个参数,这是不正确的,因为你需要第四个参数作为一个变量,你可以在其中返回答案。现在将第4个参数设置为ReturnList是好的,但是当前没有调用此子句的实例将其调用。因此,您的跟踪显示_XXXX的值(它未经实例化)。最后一个问题是问题:

    df_real(1:Column, Size, NewList, NewList).

出于某种原因,你有NewList作为第3和第4个参数。您可能希望ReturnList作为第4个参数,以便它通过递归进行并最终设置:

    df_real(1:Column, Size, NewList, ReturnList).

最后,终端(或基地)案例:

% Recursive Case: Exit when list is full.
df_real(_, N, Q, Newlist) :-
    length(Q, Length),
    N = Length.

NewList这里的第四个参数什么也没做。它是一个单例变量,并没有被任何东西填充。因此,在跟踪中,它会显示为_XXXX,并且您在ReturnList中没有答案。当Q列表已达到N时,表示您已完成该条款。我想,在那时,Q是你想要的答案。所以你只需要在Prolog中这样说:

% Recursive Case: When list is full, it's the answer
df_real(_, N, Q, Q) :-
    length(Q, N).

你也可以通过简化第一个参数来整理一下。它是X:Y形式的术语,您永远不会使用X,为什么要随身携带?

depth_first(N, ReturnList) :-
    df_real(1, N, [2:1], ReturnList).

df_real(_:NextRankC, Size, Q, ReturnList) :- 
    genInt(Size, Row), 
    Column is NextRankC + 1,
    Rank = Row:Column,
    \+ list_attack(Rank, Q),   % Note use of ISO negation predicate, \+
    add(Rank, Q, NewList),
    df_real(Column, Size, NewList, ReturnList).

% Recursive Case: When list is full, it's the answer
df_real(_, N, Q, Q) :-
    length(Q, N).