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).