我正在尝试在Prolog中创建此功能:
% Signature: circleList(L1, L2)/2
% Purpose: L2 is a "circled" L1 list.
% Precondition: L1 is fully instantiated.
% Examples:
% ?- circleList([2, 3, 4, 5], X).
% X = [2, 3, 4, 5];
% X = [3, 4, 5, 2];
% X = [4, 5, 2, 3];
% X = [5, 2, 3, 4];
% false.
所以我这样做了:
circleList([],[]).
circleList(X,X).
circleList([H|T],R):- append(T,[H],S), circleList(S,R).
但输出是这样的:
X = [2, 3, 4, 5] ;
X = [3, 4, 5, 2] ;
X = [4, 5, 2, 3] ;
X = [5, 2, 3, 4] ;
X = [2, 3, 4, 5] ;
X = [3, 4, 5, 2] ;
X = [4, 5, 2, 3] ;
X = [5, 2, 3, 4] ;
X = [2, 3, 4, 5] ;
X = [3, 4, 5, 2]
and so on...
这很好但是我想在第一次完成所有可能性之后停止它。
我能做什么?
答案 0 :(得分:3)
你的谓词需要另一个参数。一种选择是使用列表中的元素,直到您留下[]
。
circleList([Head|Tail],CL):-
circleList(Tail,[Head],CL).
circleList([],L,L).
circleList([Head|Tail], Rest, CL):-
append(Rest, [Head], NewRest),
circleList(Tail, NewRest, CL).
circleList([Head|Tail], Rest, CL):-
append([Head|Tail], Rest,CL).
我看到的另一个选项是使用length/2
将深度限制为列表大小。
circleList([],[]).
circleList(List,CL):-
length(List, N),
circleList(List,N,CL).
circleList(_,0,_):-!, fail.
circleList(List,_,List).
circleList([Head|Tail], N, CL):-
append(Tail, [Head], NewList),
N1 is N - 1,
circleList(NewList, N1, CL).
答案 1 :(得分:3)
您可能只是以不同方式制定问题:
rotatelist([], []).
rotatelist(Xs, Ys) :-
Xs = [_|_],
Ys = [_|_],
same_length(Xs, Ys), % avoid non-termination
Bs = [_|_], % avoid redundant answers
append(As,Bs,Xs),
append(Bs,As,Ys).
same_length([], []).
same_length([_E|Es], [_F|Fs]) :-
same_length(Es, Fs).
但如果你要明确停止;好吧,这很容易变成不正确的。事实上,我没有看到如何在这里使用切割的自然方式。
但是,您可能会限制递归次数,如下所示:
circleList2(Xs, Ys) :-
same_length(Xs, Ys),
circleList2(Xs, Ys, Xs).
circleList2(X,X, _).
circleList2([H|T],R, [_|L]):-
L = [_|_],
append(T,[H],S),
circleList2(S,R, L).
所以这基本上是你的程序,有一个额外的参数用于限制递归的数量。以这种方式限制递归通常用于实现所谓的迭代深化算法。然而,在这种情况下,我们只有一个深度限制。不需要额外的迭代。
答案 2 :(得分:2)
这是一个更简单的解决方案,具有更弱的终止属性。另一方面,你说第一个参数是"完全实例化"。你能否迅速地为一个论证做一个测试,以便完全实例化#34 ;?我假设没有。正是由于这个原因,这种假设导致了很多错误。首先,程序员只是假设参数将被"完全实例化"后来他们忘记了他们的假设...
circleList3(Xs, Ys) :-
append(As, Bs, Xs),
append(Bs, As, Ys),
( As = [] ; As = [_|_], Bs = [_|_] ).
此版本现在不再针对circleList3(Xs, [])
终止。要了解为何如此,我将使用failure-slice,即我将在程序中添加 false
。如果剩下的部分仍未终止,则可见部分存在一个问题。
?- circleList3(Xs, []), false. /* LOOPS */ circleList3(Xs, Ys) :- append(As, Bs, Xs), false,append(Bs, As, Ys),( As = [] ; As = [_|_], Bs = [_|_] ).
此故障片不会终止,因为第一个目标是使用3个未实例化的参数调用的。终止的唯一帮助是Ys
,但没有人对此感兴趣!
我们现在可以交换两个目标append/3
,使这个片段终止,但是,其他查询不会终止......