Как сравнить два списка со значениями и диапазонами в 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
= означает унифицировать переменные и == сравнить их, а в прологе они вызывают диапазон (X, Y) предикатом / 2, а не функцией, поэтому они не будут возвращать значение.   -  person Luai Ghunim    schedule 05.11.2017
comment
Прежде всего, эти списки отсортированы или нет? Я спрашиваю, потому что пример отсортирован.   -  person Armatorix    schedule 05.11.2017
comment
Второе... Прежде чем вставлять код, проверьте, правильно ли он скопирован. У вас нет знака ')' во 2-й строке предиката find. Следующим шагом является использование имен, которые используются в стандартной библиотеке. Я бы не рекомендовал это.   -  person Armatorix    schedule 05.11.2017


Ответы (1)


Итак, если ввод не нужно сортировать, вот решение

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

Проверяет, находится ли один из концов rangeB в диапазоне rangeA.

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
Приведите пример, который не работает, пожалуйста. - person Armatorix; 05.11.2017
comment
Ладно, виноват, починил. Достаточно было проверить numInRange, является ли аргумент числом с помощью функции number/1. - person Armatorix; 05.11.2017
comment
Это именно то решение, которое я узнаю. Спасибо еще раз :) - person tshn; 05.11.2017