我创建了一个谓词enum
,它带有一个列表和一个数字,例如[1,2,3,4]
和3
,并返回一个包含长度为3的列表的列表。清单介绍。所以在给定enum([1,2,3,4],3,[[1,2,3],[2,3,4]])
的示例中。
我创建了一个只接受长度为N的第一个列表的函数,但是当我尝试将其循环以获取所有其他列表时,我会收到错误。谢谢你的帮助。
append([],L,L).
append([H|T],L2,[H|L3]):- append(T,L2,L3).
len([],0).
len([_|B],X):- len(B,X1), X is X1+1.
take(_,X,Y) :- X =< 0, !, X =:= 0, Y = [].
take([],_,[]).
take([A|B],X,[A|C]):- Z is X-1, take(B,Z,C).
enum([],_,[]).
enum([N1|N2],N3,N4):-
len([N1|N2],U),
N3=<U,
take([N1|N2],N3,T1),
append([N4],[T1],T2),
!,
enum(N2,N3,T2).
答案 0 :(得分:0)
我将专注于take/3
谓词,这是你问题的核心。为了获得[2,3,4]
[1,2,3,4]
之类的子列表,您必须能够跳过第一个元素,并获取其余元素的子列表。
您可以通过在您的定义中添加此子句来实现此目的:
take([_|Xs], N, Ys) :- take(Xs, N, Ys).
有了这个,您现在可以获得长度为3的几个不同的子列表,还有一些其他多余的解决方案:
?- take([1,2,3,4], 3, Xs).
Xs = [1, 2, 3] ;
Xs = [1, 2, 4] ;
Xs = [1, 2] ;
Xs = [1, 3, 4] ;
Xs = [1, 3] ;
Xs = [1, 4] ;
Xs = [1] % etc.
这是因为您的子句take([], _, [])
接受一个空列表作为任何长度的&#34;子列表&#34;一个空列表。我想你只想接受空列表作为长度为0的子列表。如果你删除这个子句,你的第一个子句将强制执行,你只得到长度恰好为3的解决方案:
?- take([1,2,3,4], 3, Xs).
Xs = [1, 2, 3] ;
Xs = [1, 2, 4] ;
Xs = [1, 3, 4] ;
Xs = [2, 3, 4] ;
false.
作为附注,你的第一个条款没有问题,但它可以简化为:
take(_,X,Y) :- X = 0, !, Y = [].
我还建议您使用更易读的变量名称。对于列表长度等数字,我们经常使用N
。对于列表,通常会将Xs
,Ys
等名称与X
,Y
等一起用于相应列表的成员。
最后,要查找谓词的所有解法,您需要使用系统谓词,如setof
,bagof
或findall
。无法在纯Prolog中编写enum
。
答案 1 :(得分:0)
因为我不确定其他答案中的建议,所以这是我对你的问题的看法。
首先,不要定义自己的append/3
和length/2
,append/3
现在是Prolog民间传说,您可以在textbooks 30 years old找到它。 length/2
很难自行解决,使用内置功能。</ p>
现在:要获取列表N
前面的第一个L
元素,您可以说:
length(Front, N),
append(Front, _, L)
您可以创建所需长度的列表,然后使用append/3
从您的列表中拆分前面。
考虑到这一点,定义谓词sliding_window/3
:
sliding_window(L, N, [L]) :-
length(L, N).
sliding_window(L, N, [W|Ws]) :-
W = [_|_], % W should be at least one long
length(W, N),
append(W, _, L),
L = [_|L0],
sliding_window(L0, N, Ws).
这种作品,但在给你所有有用的答案之后它会循环:
?- sliding_window([a,b], N, Ws).
N = 2,
Ws = [[a, b]] ;
N = 1,
Ws = [[a], [b]] ;
% loops
它因为相同的小片段而循环:
length(Front, N),
append(Front, _, L)
使用length/2
,您可以继续生成长度增加的列表;一旦Front
超过L
,append/3
将失败,length/2
会生成更长的列表,依此类推。
其中一种方法是使用between/3
来约束前线的长度。如果你把它放在自己的谓词中:
front_n(L, N, F) :-
length(L, Max),
between(1, Max, N),
length(F, N),
append(F, _, L).
有了这个:
sliding_window(L, N, [L]) :-
length(L, N).
sliding_window(L, N, [W|Ws]) :-
front_n(L, N, W),
L = [_|L0],
sliding_window(L0, N, Ws).
现在它终于奏效了:
?- sliding_window([a,b,c,d], 3, Ws).
Ws = [[a, b, c], [b, c, d]] ;
false.
?- sliding_window([a,b,c], N, Ws).
N = 3,
Ws = [[a, b, c]] ;
N = 1,
Ws = [[a], [b], [c]] ;
N = 2,
Ws = [[a, b], [b, c]] ;
false.
练习:摆脱无害但不必要的选择点。