Я новичок в PROLOG, и я нахожу его довольно сложным. Мне нужно вернуть 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.
Любые идеи, как я могу реализовать такую программу?
Спасибо
Вот мой подход, вы можете использовать flatten.
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
Спасибо за быстрый ответ. сравнить([22,[100,36],1],[[36,100],[22,1]]). хотя должно быть ложным. Идея заключается в том, что если 2 списка содержат подсписки, которые содержат одни и те же элементы, независимо от их положения, то вывод должен быть истинным. Так что мне нужно, чтобы 2 списка содержали не только одни и те же элементы, но и одни и те же подсписки. Как пример, который я привел. Спасибо
Это должно быть правдой, первый список после сглаживания становится: [22,100,36,1], а второй [36,100,22,1]. Следовательно, при сравнении должно быть правдой.
@user14819924 user14819924 хорошо, это другая концепция. Дайте-ка подумать.
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).
Пролог не возвращает
true
илиfalse
. На самом деле он ничего не возвращает. Программа либо преуспевает, либо терпит неудачу. Если это удастся, вы можете проверить переменные в своем запросе и увидеть их значения.