我的文件(position(M,P))
中已有大量事实,M是名称,P是玩家的位置,我被要求做player_list(L,N)
,L是球员列表和N是此列表的大小。我做到了它的工作问题是,它给出的列表没有名称,它给我数字而不是名称
player_list([H|T],N):- L = [H|T],
position(H,P),
\+ member(H,L),
append(L,H),
player_list(T,N).
我得到的是:
?- player_list(X,4).
X = [_9176, _9182, _9188, _9194] .
那我该怎么办?
答案 0 :(得分:4)
您可以使用其他列表作为参数来跟踪您已有的玩家。此列表在开头是空的,因此调用谓词调用描述与[]
的实际关系的谓词作为附加参数:
player_list(PLs,L) :-
pl_l_(PLs,L,[]). % <- actual relation
您发布的定义缺少基本情况,也就是说,如果您已经拥有所需数量的玩家,则可以停止添加其他玩家。在这种情况下,要添加的玩家数量为零,否则大于零。你还必须描述列表的头部(PL
)是一个玩家(你不关心它的位置,所以变量前面有一个下划线(_P
),否则就是目标就像在你的代码中一样)并且还没有在累加器中(与你的代码相反,你检查PL
是否不在L
中)但是在递归调用中它在累加器中。您可以通过在递归目标中使用[PL|Acc0]
来实现后者,因此您不需要append/2
。将所有这些放在一起,您的代码可能如下所示:
pl_l_([],0,_). % base case
pl_l_([PL|PLs],L1,Acc0) :-
L1 > 0, % number of players yet to add
L0 is L1-1, % new number of players to add
position(PL,_P), % PL is a player and
\+ member(PL,Acc0), % not in the accumulator yet
pl_l_(PLs,L0,[PL|Acc0]). % the relation holds for PLs, L0 and [PL|Acc0] as well
关于你的评论,我认为你的代码包含以下四个事实:
position(zlatan,center).
position(rooney,forward).
position(ronaldo,forward).
position(messi,forward).
然后您的示例查询会产生所需的结果:
?- player_list(X,4).
X = [zlatan,rooney,ronaldo,messi] ? ;
X = [zlatan,rooney,messi,ronaldo] ? ;
...
如果你打算反过来使用谓词,我建议使用CLP(FD)。要了解原因,请考虑最常见的查询:
?- player_list(X,Y).
X = [],
Y = 0 ? ;
ERROR at clause 2 of user:pl_l_/3 !!
INSTANTIATION ERROR- =:=/2: expected bound value
您收到此错误是因为>/2
期望两个参数都被接地。您可以修改谓词pl_l_/3
以使用CLP(FD),如下所示:
:- use_module(library(clpfd)).
pl_l_([],0,_).
pl_l_([PL|PLs],L1,Acc0) :-
L1 #> 0, % <- new
L0 #= L1-1, % <- new
position(PL,_P),
\+ member(PL,Acc0),
pl_l_(PLs,L0,[PL|Acc0]).
通过这些修改,谓词更加通用:
?- player_list([zlatan,messi,ronaldo],Y).
Y = 3
?- player_list(X,Y).
X = [],
Y = 0 ? ;
X = [zlatan],
Y = 1 ? ;
X = [zlatan,rooney],
Y = 2 ?
...