Как да сравните два списъка със стойности и диапазони в Prolog

Правя проект и съм заседнал в ситуация, в която трябва да сравня два списъка и да се върна, ако поне един член от списък е в друг списък. Доста просто, но списъците може да съдържат не само числа, но и набор от числа. Нещо като: [1,3,обхват(5,10),25]

Мисля, че основният ми проблем е повторението на списъците, защото връща true само ако първият член на списъка съвпада с атома. Това е моят код за сравнение:

findin(E,[H|T]) :-
    E == H ;
    (H == range(X,Y), E \== range(Xe,Ye), between(X,Y,E)) ;
    (E == range(Xe,Ye), H \== range(X,Y), between(Xe,Ye,H)) ;
    (E == range(Xe,Ye), H == range(X,Y), (between(X,Y,Xe) ; between(Xe,Ye,X))) , 
    findin(E,T).

И кодът за извикване на функцията findin/2:

find([Ha|Ta],[Hb|Tb]) :-
    findin(Ha,[Hb|Tb]),
    find(Ta,[Hb|Tb]).

пропускам нещо? Също така, някакви идеи за повторение на списъци A и B от функцията find/2?


person tshn    schedule 04.11.2017    source източник
comment
= означава обединяване на променливи и == сравняването им и в prolog те извикват range(X,Y) предикат/2, а не функция, така че няма да върнат стойност.   -  person Luai Ghunim    schedule 05.11.2017
comment
Първо, сортирани ли са тези списъци или не са? Питам, защото примерът е подреден.   -  person Armatorix    schedule 05.11.2017
comment
Второ нещо... Преди да поставите кода, проверете дали е правилно копиран. Нямате знак „)“ във втория ред на предиката за търсене. Следващото нещо е използването на именуване, което се използва в стандартната библиотека. Не бих го препоръчал.   -  person Armatorix    schedule 05.11.2017


Отговори (1)


Така че, ако входът не трябва да се сортира, ето решение

doubleRangeCheck(range(Xa,Ya),range(Xb,Yb)) :-
    between(Xa,Ya,Xb) ; between(Xa,Ya,Yb),!.

Проверява дали един от краищата на диапазон B е в диапазон A.

numInRange(number(A),range(Xb,Yb)) :-
    between(Xb,Yb,A),!.

Проверява дали числото е в диапазона

findInX(A,[Hb|Tb]) :-
    A = Hb ;
    (doubleRangeCheck(A,Hb); doubleRangeCheck(Hb,A));
    numInRange(A,Hb);
    numInRange(Hb,A);
    findInX(A,Tb),!.

Проверка дали: 1. ако и двата елемента са еднакви, 2. ако един диапазон съдържа някой от други диапазони завършва и обратното (проверявахте лошо 2 диапазона случай), 3/4. Проверка дали num е в диапазон (и дали Hb или A изобщо са диапазони), 5. ...

findX([Ha|Ta],[Hb|Tb]) :-
    findInX(Ha,[Hb|Tb]);
    findX(Ta,[Hb|Tb]),!.

Част, която беше добра, с изключение на затварящата скоба.

Ако входът трябва да бъде сортиран, можете да използвате някакъв вид сортиране чрез сливане, би било МНОГО ПО-ефективно и интересно. Препоръчваме да направите този случай сами.

person Armatorix    schedule 04.11.2017
comment
Благодаря за вашата помощ! Връща очаквано цяло число за грешка, намерено съединение... когато диапазон A е по-голям или по-нисък от диапазон B, но предполагам, че мога да разбера какво да направя. Между другото, това е несортиран списък. - person tshn; 05.11.2017
comment
Дайте ми пример, който не е worring, моля. - person Armatorix; 05.11.2017
comment
Добре, моя е грешката, поправих го. Беше достатъчно да се провери в numInRange дали arg е число с функция number/1. - person Armatorix; 05.11.2017
comment
Точно това е решението, което намирам. Благодаря отново :) - person tshn; 05.11.2017