Prolog - 比较包含其他列表作为元素的 2 个列表
Prolog - compare 2 lists that contain other lists as elements
我是 PROLOG 的新手,我觉得它很有挑战性。
如果 2 个列表具有相同的元素(它们相等),我需要 return 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.
有什么想法可以实现这样的程序吗?
谢谢
这是我的方法,你可以使用展平。
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
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
)。
递归排序谓词的更简洁的实现,使用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).
我是 PROLOG 的新手,我觉得它很有挑战性。 如果 2 个列表具有相同的元素(它们相等),我需要 return 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.
有什么想法可以实现这样的程序吗?
谢谢
这是我的方法,你可以使用展平。
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
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
)。
递归排序谓词的更简洁的实现,使用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).