List 测试列表中的所有列表是否具有相同的长度
我试图在Prolog中学习更多关于列表的知识,尤其是列表中的列表。所以我想写一个谓词来确定列表中的列表是否相等。所以如果我这么做了List 测试列表中的所有列表是否具有相同的长度,list,prolog,clpfd,prolog-coroutining,meta-predicate,List,Prolog,Clpfd,Prolog Coroutining,Meta Predicate,我试图在Prolog中学习更多关于列表的知识,尤其是列表中的列表。所以我想写一个谓词来确定列表中的列表是否相等。所以如果我这么做了 ?- equalLists([[a,b,c],[1,2,3],[d,4,e],[5,6]]). false 因此,我试图检查每个列表,看看它是否与前一个列表具有相同的长度。有人能给我指出正确的方向吗?首先,我们定义一些标准的高阶关系,map和fold。这需要内置的调用谓词。可以将maxlist等定义为一次性,但这应该更具启发性 其思想是得到一个长度列表,然后比较列
?- equalLists([[a,b,c],[1,2,3],[d,4,e],[5,6]]).
false
因此,我试图检查每个列表,看看它是否与前一个列表具有相同的长度。有人能给我指出正确的方向吗?首先,我们定义一些标准的高阶关系,
map
和fold
。这需要内置的调用谓词。可以将maxlist
等定义为一次性,但这应该更具启发性
其思想是得到一个长度列表,然后比较列表中的最大值是否等于最小值
maplist(_, [], []).
maplist(P, [X | Y], [A | B]) :-
call(P, X, A),
maplist(P, Y, B).
max(A, B, M) :- A < B, M = B.
max(A, B, M) :- A >= B, M = A.
min(A, B, M) :- B < A, M = B.
min(A, B, M) :- B >= A, M = A.
fold(_, [X], X).
fold(P, [X, Y], R) :- call(P, X, Y, R).
fold(P, [X, Y | Z], R) :-
fold(P, [Y | Z], NR),
call(P, NR, X, R).
maxlist(L, M) :- fold(max, L, M).
minlist(L, M) :- fold(min, L, M).
equallists(L) :-
maplist(length, L, Lengths),
maxlist(Lengths, Max),
minlist(Lengths, Min),
Max == Min.
maplist(u,[],[])。
地图列表(P[X|Y],[A|B]):-
呼叫(P,X,A),
地图列表(P,Y,B)。
最大值(A,B,M):-A=B,M=A。
最小值(A,B,M):-B=A,M=A。
折叠(X,[X],X)。
折叠(P,[X,Y],R):-调用(P,X,Y,R)。
褶皱(P[X,Y | Z],R):-
褶皱(P[Y | Z],NR),
呼叫(P、NR、X、R)。
最大列表(L,M):-折叠(最大,L,M)。
最小列表(L,M):-折叠(最小,L,M)。
平等主义者(L):-
地图列表(长度、L、长度),
最大列表(长度,最大值),
最小列表(长度,最小值),
最大值==最小值。
@Peteris的解决方案过于复杂。您可以这样做:
equal_lengths([]).
equal_lengths([[]]).
equal_lengths([[_|_]]).
equal_lengths([X,Y|Rest]) :-
length(X, Len),
length(Y, Len),
equal_lengths([Y|Rest]).
归纳地思考。我断言空列表的长度和一个列表的长度是“相等的”(没有/只有一个可以比较)。然后我说如果第一个项目的长度等于第二个项目的长度,只要第二个项目的长度和其他项目的长度匹配,我们就可以了
注意:我们并没有明确地说X和Y的长度与某种等式测试相同。我们让Prolog为我们处理这个问题,只需声明X和Y的长度是Len。因此,如果Y的长度与X的长度不一致,谓词将失败
逆转过程
因此,要编写一个谓词来确定列表是否没有相同的长度,我们必须注意,这次我们必须跟踪到目前为止看到的要检查的长度。我们必须将每个列表的长度与前面所有列表的长度进行比较,以确定不平等性。因此,这次我们的初始案例将创建初始长度列表,并将处理延迟到另一个谓词,如:
unequal_lengths(X) :- unequal_lengths(X, []).
现在,我们再次从类似的基本情况开始:
unequal_lengths([], _).
unequal_lengths([[]], _).
unequal_lengths([[_|_]], _).
当我们有一个实际的列表时,事情会变得有趣:
unequal_lengths([X|Rest], Lengths) :-
length(X, Len),
\+ member(Len, Lengths),
unequal_lengths(Rest, [Len|Lengths]).
因此,我们计算这个列表的长度,然后断言这不是我们以前使用handy成员谓词看到的长度,然后将这个长度连同其余部分一起传递给列表的其余部分
附录:不平等与所有
受其他答案的启发,您可以以高阶方式实现不等_长度,如下所示:
unequal_lengths(Lists) :-
findall(Len, (member(X, Lists), length(X, Len)), Lengths),
forall(select(Len, Lengths, Remaining), \+ member(Len, Remaining)).
仔细想想,这与问题的形式逻辑表达式非常接近:对于每个列表长度,不存在与此长度对应的剩余列表长度的元素。我将使用SWI Prolog内置项重写Peteris答案(+1),并:
完成了
更简单的是,使用(此处)调整参数顺序:
:- [lambda].
equallists([H|T]) :-
length(H, N),
maplist(\L^length(L, N), T).
南特马Variazione(这应该是最低限度的):
如@false所述,当T不接地时,测试可能失败。可能的更正:
equallists([H|T]) :-
length(H, N),
forall(member(L, T), (nonvar(L), length(L, N))).
对于all/2,我认为它可以被描述为故障驱动循环的一种形式,很容易被误用
当然,Prolog中的每个控制流结构都很难正确使用,这可能是该语言很少流行的主要原因。我发现唯一可以接受的解决方案是chac的最后一个,为了完整性,我添加了空列表处理:
equalLengths([]).
equalLengths([Head|Tail]) :-
length(Head, Length),
forall(member(List, Tail), length(List, Length)).
使用正确的工具——和——我们只需要一行:
?- Xss = [[1,2],[2,3],[3,4,5]], maplist(N+\Xs^length(Xs,N),Xss).
false.
?- Xss = [[1,2],[2,3],[3,4]], maplist(N+\Xs^length(Xs,N),Xss).
N = 2.
?-Xss=[[1,2],[2,3],[3,4,5]],映射列表(N+\Xs^长度(Xs,N),Xss)。
错。
?-Xss=[[1,2],[2,3],[3,4]],映射列表(N+\Xs^长度(Xs,N),Xss)。
N=2。
(+\)/2
帮助我们声明N
是免费的,因此我们使用与N
相同的N
作为Xss
中每个的长度Xss
这是一种解决方案,它利用了大多数Prolog系统中发现的第一个参数索引,以避免在大多数(但不是所有)情况下出现虚假的选择点:
一些示例查询:
| ?- equal_lengths([]).
yes
| ?- equal_lengths([[]]).
yes
| ?- equal_lengths([_]).
yes
| ?- equal_lengths([[],_]).
yes
| ?- equal_lengths([_,[]]).
true ? ;
no
| ?- equal_lengths([L1,L2]).
L1 = []
L2 = [] ? ;
L1 = [_]
L2 = [_] ? ;
L1 = [_,_]
L2 = [_,_] ?
...
| ?- equal_lengths([[a,b,c],[1,2,3],[d,4,e],[5,6]]).
no
| ?- equal_lengths([[a,b,c],[1,2,3],[d,4,e],[5,6,7],L]).
L = [_,_,_]
yes
| ?- equal_lengths([L1,[_,_],L3]).
L1 = [_,_]
L3 = [_,_] ? ;
no
| ?- equal_lengths([L1,[_,_|_],L3]).
L1 = [_,_]
L3 = [_,_] ? ;
L1 = [_,_,_]
L3 = [_,_,_] ? ;
L1 = [_,_,_,_]
L3 = [_,_,_,_] ? ;
...
?- Xss = [As,Bs,Cs], As=[], samelength_of(N,Xss).
N = 0, Xss = [[],[],[]], As = [], Bs = [], Cs = [].
?- Xss = [As,Bs,Cs], samelength_of(N,Xss), As=[].
N = 0, Xss = [[],[],[]], As = [], Bs = [], Cs = [].
当第一个元素未绑定且存在绑定列表元素时,我们只会得到一个虚假的选择点(即不会导致解决方案的选择点)。如果没有列表元素绑定到有限的列表,谓词将生成列表长度不断增长的解决方案,如示例查询中所示。遵循第二个解决方案,与第一次尝试相比具有更好的终止属性。主要思想是在每次遍历列表时,我们从每个列表中删除一个元素
equal_lengths([]).
equal_lengths([L1| Ls]) :-
pick(L1, Ls, Rs),
equal_lengths(Rs).
pick([], Ls, []) :-
all_empty(Ls).
pick([_| R1], Ls, [R1| Rs]) :-
pick(Ls, Rs).
pick([], []).
pick([[_|R1]| Ls], Rs) :-
pick([_|R1], Ls, Rs).
all_empty([]).
all_empty([[]| Rs]) :-
all_empty(Rs).
在对我的第一个解决方案的评论中提到的问题案例@false是:
| ?- equal_lengths([_,_,[]]).
true ? ;
no
但是,更清楚的是,如果不使用匿名变量,我们可以得到唯一正确的解决方案:
| ?- equal_lengths([L1,L2,[]]).
L1 = []
L2 = [] ? ;
no
在我的第一个解决方案中,前面的所有示例查询都没有问题。有一个查询特别值得一提,因为它错误地只提供了一个解决方案,而没有在以前的尝试中生成解决方案。现在它如预期的那样工作:
| ?- equal_lengths([L]).
L = [] ? ;
L = [_] ? ;
L = [_,_] ? ;
L = [_,_,_] ? ;
...
有人能找到导致此解决方案出现问题的示例查询吗?我菜单上的下一道菜:大杂烩
:- use_module(library(clpfd)).
samelength_of(N,Xss) :- maplist(length_of__lazy(N),Xss).
length_of__lazy(N,Xs) :-
N #>= 0,
( nonvar(N)
-> length(Xs,N)
; var(Xs)
-> when((nonvar(Xs);nonvar(N)), length_of__lazy(N,Xs))
; Xs = []
-> N = 0
; Xs = [_|Xs0]
-> N0 + 1 #= N,
length_of__lazy(N0,Xs0)
; throw(error(type_error(list,Xs),length_of__lazy/2))
).
my_indomain(N) :-
fd_inf(N,I),
( N #= I
; N #> I, my_indomain(N)
).
一些示例查询:
| ?- equal_lengths([]).
yes
| ?- equal_lengths([[]]).
yes
| ?- equal_lengths([_]).
yes
| ?- equal_lengths([[],_]).
yes
| ?- equal_lengths([_,[]]).
true ? ;
no
| ?- equal_lengths([L1,L2]).
L1 = []
L2 = [] ? ;
L1 = [_]
L2 = [_] ? ;
L1 = [_,_]
L2 = [_,_] ?
...
| ?- equal_lengths([[a,b,c],[1,2,3],[d,4,e],[5,6]]).
no
| ?- equal_lengths([[a,b,c],[1,2,3],[d,4,e],[5,6,7],L]).
L = [_,_,_]
yes
| ?- equal_lengths([L1,[_,_],L3]).
L1 = [_,_]
L3 = [_,_] ? ;
no
| ?- equal_lengths([L1,[_,_|_],L3]).
L1 = [_,_]
L3 = [_,_] ? ;
L1 = [_,_,_]
L3 = [_,_,_] ? ;
L1 = [_,_,_,_]
L3 = [_,_,_,_] ? ;
...
?- Xss = [As,Bs,Cs], As=[], samelength_of(N,Xss).
N = 0, Xss = [[],[],[]], As = [], Bs = [], Cs = [].
?- Xss = [As,Bs,Cs], samelength_of(N,Xss), As=[].
N = 0, Xss = [[],[],[]], As = [], Bs = [], Cs = [].
比目鱼不是你的口味吗?没问题
你的第二种情况应该是等长([[[]]])。
-你不希望任何非列表列表成功。刚刚意识到我们需要另一种基本情况,等长([]])。
我有另一个简单的问题,我该如何扭转这种情况。就像我想确保所有列表都不相等一样。@NickBarnes在这种情况下可能不是
?- Xss = [As,Bs,Cs], As=[], samelength_of(N,Xss).
N = 0, Xss = [[],[],[]], As = [], Bs = [], Cs = [].
?- Xss = [As,Bs,Cs], samelength_of(N,Xss), As=[].
N = 0, Xss = [[],[],[]], As = [], Bs = [], Cs = [].
?- samelength_of(N,[As,Bs,Cs]).
N in 0..sup,
when((nonvar(As);nonvar(N)), length_of__lazy(N,As)),
when((nonvar(Bs);nonvar(N)), length_of__lazy(N,Bs)),
when((nonvar(Cs);nonvar(N)), length_of__lazy(N,Cs)).
?- samelength_of(N,[As,Bs,Cs]), my_indomain(N).
N = 0, As = [], Bs = [], Cs = [] ;
N = 1, As = [_A1], Bs = [_B1], Cs = [_C1] ;
N = 2, As = [_A1,_A2], Bs = [_B1,_B2], Cs = [_C1,_C2] ;
N = 3, As = [_A1,_A2,_A3], Bs = [_B1,_B2,_B3], Cs = [_C1,_C2,_C3] ...