List Prolog递归调用

List Prolog递归调用,list,recursion,prolog,List,Recursion,Prolog,我在递归搜索列表和根据结果创建列表列表时遇到问题 知识库包含团队名称、获胜次数和他们所在的区域,所有这些都与他们的团队编号关联。我正在传递团队中的团队编号列表,并且正在使用findMinMax/3搜索匹配对。我需要的结果是 成对团队列表(例如,X=[[gonzaga,华盛顿],[iowa,oklahoma],…]) 和1个不匹配的团队(由奇数个团队组成)或0个(偶数情况下) 我知道了所有其他的事情,并且可以达到部分[gonzaga,washington],但是在递归部分失败了 findPair(

我在递归搜索列表和根据结果创建列表列表时遇到问题

知识库包含团队名称、获胜次数和他们所在的区域,所有这些都与他们的团队编号关联。我正在传递
团队中的团队编号列表
,并且正在使用
findMinMax/3
搜索匹配对。我需要的结果是

成对团队列表(例如,
X=[[gonzaga,华盛顿],[iowa,oklahoma],…]
) 和1个不匹配的团队(由奇数个团队组成)或0个(偶数情况下)

我知道了所有其他的事情,并且可以达到部分
[gonzaga,washington]
,但是在递归部分失败了

findPair(Teams,[HL|TL],Rest) :-
    findMinMax(Teams,Min,Max),
    delete(Teams,Min,TeamsNoMin),
    delete(TeamsNoMin,Max,Rest),
    createPair(Min,Max,Pair), %Pair = "["Min_team","Max_team"]"
    append(HL,[Pair],TL),
    findPair(Rest,TL,[]).
一种通用的递归格式 在这里,我将尝试向您展示我们通常如何在Prolog中执行递归。对于初学者来说,获取列表并不简单,因为列表是“向后”构建的:在我们到达列表的末尾之前,没有任何东西能够真正构建

这种“向后构建”原则的原因是,一旦设置了一个变量,就不能将其设置为另一个值,因此,例如,很难说递归的第一步结果是
[1]
,然后变成
[1,2]
。相反,我们在Prolog中说的是,结果头是
1
,结果尾是递归调用的结果(是的,如果它变得凌乱,请读两遍:d)。因此,只要我们没有碰到基本情况(没有执行递归的情况),我们就不会明确地绑定变量(即我们总是让术语的一部分未绑定)

对于谓词
rec/2:rec(Input,Result)
通过将其元素与
somepredicate/2
链接,从输入列表生成结果列表,我们将这样写:

rec([InputHead|InputTail], [ResultHead|ResultTail]) :-
    somepredicate(InputHead, ResultHead),
    rec(InputTail, ResultTail).
代表这一点

在这里您可以看到,我们声明结果的头部是
ResultHead
,其尾部是通过调用
rec(InputTail,ResultTail)计算出来的。

现在这很好,但我们需要在某个点停止,例如,当列表为空时。我们将这样写:

rec([], []).
这意味着:当输入列表为空时,结果列表也是空的

谓词的应用程序 现在,要解决问题,首先必须解决递归子句:

findPair(Teams,[HL|TL],Rest) :-
    findMinMax(Teams,Min,Max),
    delete(Teams,Min,TeamsNoMin),
    delete(TeamsNoMin,Max,Rest),
    createPair(Min,Max,Pair), %Pair = "["Min_team","Max_team"]"
    append(HL,[Pair],TL),
    findPair(Rest,TL,[]).
将成为

findPair(Teams, [Pair|Tail], LeftOver) :-
    findMinMax(Teams, Min, Max),
    delete(Teams, Min, TeamsNoMin),
    delete(TeamsNoMin, Max, Rest),
    createPair(Min, Max, Pair), %Pair = "["Min_team","Max_team"]"
    findPair(Rest, Tail, LeftOver).
需要注意的重要事项:现在
Rest
已成为两个独立的变量。
findPair/3
的最后一个参数不再被更改,因为在递归调用中我们还不知道它的任何信息,所以我们无法绑定它,因此,in谓词
Rest
现在是独立的,只代表尚未处理的团队,因此对结果列表的尾部(以及
剩余的
)感兴趣

现在我们必须处理基本情况:

  • 当没有队伍的时候

    findPair([], [], []).
    
    这里我们说当
    团队
    为空时,
    结果
    剩余
    也是空的

  • 当剩下一队的时候

    findPair([Last], [], [Last]).
    
    这里我们说,当
    团队
    只有一个元素时,
    剩余
    等于
    团队
    ,并且
    结果
    为空

生成的代码是:

findPair([], [], []).
findPair([Last], [], [Last]).
findPair(Teams, [Pair|Tail], LeftOver) :-
    findMinMax(Teams, Min, Max),
    delete(Teams, Min, TeamsNoMin),
    delete(TeamsNoMin, Max, Rest),
    createPair(Min, Max, Pair), %Pair = "["Min_team","Max_team"]"
    findPair(Rest, Tail, LeftOver).
要使您的子句具有排他性,您可以将
团队
替换为
[Not,Empty | AtAll]
,以确保最后一个子句仅用于长度为2或更长的列表,或者只需在子句开头添加一个保护,例如
团队=[\uuuuu,| uuu],


希望有帮助,请不要犹豫,在评论中要求澄清:)

感谢您的详细帮助!我知道我需要一些基本情况,但不确定该去哪里,因为我不能正确地找出递归部分。经过一段时间的修改,我终于可以让它工作了!Prolog快杀了我,我已经两周没学了。。。谢谢你的帮助,莫格!!!你应该接受一个你认为已经回答了你问题的答案。单击答案旁边的一个大的空V形轮廓。这将使你的声誉得分增加+2,并向所有人表明你的问题已经解决。当您有15个代表时,您还可以对任何您认为是好答案的答案进行投票。:)