提问人:user14819924 提问时间:12/14/2020 更新时间:12/15/2020 访问量:122
Prolog - 比较 2 个包含其他列表作为元素的列表
Prolog - compare 2 lists that contain other lists as elements
问:
我是PROLOG的新手,我发现它非常具有挑战性。 如果 2 个列表具有相同的元素(它们相等),无论它们在列表中的位置如何,我都需要返回 T/F。 到目前为止,如果它们的元素由字符、字符串或数字组成,我可以轻松比较 2 个列表。 但是我找不到如何比较包含数字和数字列表或字符列表和字符列表的列表。
例如:
?- compare([[15,7,5],9,4],[4,[5,15,7],9])
true.
但:
?- compare([22,[100,36],1],[[36,100],[22,1]])
false.
?- compare([22,[100,36],1],[[[36,100]],22,1])
false.
?- compare([22,100,36,1],[[36,100,22,1]])
false.
我有什么想法可以实施这样的计划吗?
谢谢
答:
0赞
Reema Q Khan
12/14/2020
#1
这是我的方法,你可以使用扁平化。
1.首先使用is_list查找所有内部列表,然后使用innerListCheck谓词比较内部列表。flatten 只是将所有内部列表合并为一个列表。展平两个列表,然后检查两个列表的长度是否相等。之后,使用 checkmember 谓词。
2. checkmember 谓词将第一个列表的元素与第二个列表进行检查。如果第一个列表的所有元素都存在于第二个列表中,则它们是相同的。
compare(List1,List2):-
list(List1,A1),
list(List2,A2),
innerListCheck(A1,A2),
flatten(List1,[W1|R1]),
flatten(List2,Res2),
length([W1|R1],Len1),
length(Res2,Len2),
Len1=Len2,
checkmember([W1|R1],Res2).
checkmember([],_).
checkmember([H|T],List2):-
( member(H,List2)->
checkmember(T,List2)).
innerListCheck([],[]).
innerListCheck([H|T],[H2|T2]):-
check2(H,H2),
innerListCheck(T,T2).
check2([],_).
check2([H|T],[H2|T2]):-
member(H,[H2|T2]),
check2(T,[H2|T2]).
list([],[]).
list([H|T],[H|B]):-
is_list(H),
list(T,B).
list([H|T],B):-
\+is_list(H),
list(T,B).
例:-
?-compare([22,[100,36],1],[[36,100],[22,1],[9]]).
false
?-compare([22,100,36,1],[[36,100,22,1]])
false
?-compare([22,[100,36],1],[[[36,100]],22,1])
false
?-compare([22,100,36,1],[[36,100,22,1]])
false
?-compare([[15,7,5],9,4],[4,[5,15,7],9])
true
false
评论
0赞
user14819924
12/14/2020
感谢您的快速回答。比较([22,[100,36],1],[[36,100],[22,1]])。不过应该是假的。这个概念是,如果 2 个列表包含包含相同元素的子列表,而不管它们的位置如何,那么输出应该是 true。所以我有点需要 2 个列表不仅包含相同的元素,而且还包含相同的子列表。就像我举的例子一样。谢谢
0赞
Reema Q Khan
12/14/2020
应该是正确的,展平后的第一个列表变为:[22,100,36,1]和第二个[36,100,22,1]。因此,比较时应该是正确的。
0赞
Reema Q Khan
12/14/2020
@user14819924好吧,这是一个不同的概念。让我想想。
0赞
DuDa
12/14/2020
#2
list([]) :- !.
list([_|_]) :- !.
reccheck([],[]).
reccheck([H|T],[HH|TT]):-
recSort(H,HH),
reccheck(T,TT).
recSort(L,L):-
\+ list(L).
recSort(In,Out):-
list(In),
reccheck(In,SubSortL),
sort(SubSortL,Out).
compare(L1,L2):-
recSort(L1,LL),
recSort(L2,LL).
?- compare([[15,7,5],9,4],[4,[5,15,7],9]).
true ;
false.
?- compare([22,[100,36],1],[[36,100],[22,1]]).
false.
?- compare([22,[100,36],1],[[[36,100]],22,1]).
false.
?- compare([22,100,36,1],[[36,100,22,1]]).
false.
因此,我的解决方案对任何子列表进行递归排序,并比较两个排序列表是否相同。递归排序需要两个谓词。一个用于排序(递归)列表 (),另一个用于遍历列表并将排序应用于列表 () 的所有元素。recSort/2
recSort
reccheck/2
0赞
slago
12/15/2020
#3
只是递归排序谓词的更简洁的实现,通过使用:maplist/3
rsort(A, B) :-
( is_list(A)
-> sort(A, S), % sort input list
maplist(rsort, S, B) % recursively sort each element of the sorted input list
; A = B ).
compare(A, B) :-
rsort(A, S),
rsort(B, S).
评论
true
false