Извлечение всех чисел из заданного интервала в Prolog

#prolog #clpfd

#пролог #clpfd

Вопрос:

Я новичок в мире Prolog, и я хотел бы написать правило, которое возвращает все элементы в определенном диапазоне.

Я намерен сделать что-то вроде

Пример:

 foo(X, Low, High) :- X > Low, X < High.
  

И когда я набираю foo(X, 2, 5), он должен возвращать 3, а затем 4.

Кажется, что мой подход неверен, и я хотел бы знать, какой правильный способ сделать это.

Ответ №1:

При такой записи Prolog не знает, какие числа вам нужны (и нужны ли вам вообще числа).

Одним из способов реализации этого было бы:

 range(X, L, H) :- X is L   1, X < H.
range(X, L, H) :- L1 is L   1, L1 < H, range(X, L1, H).
  

Ответ №2:

простой ответ: between/3 :

 ?- between(3,4,X).
X = 3 ;
X = 4.
  

реализация точного поведения довольно тривиальна таким образом.

причина, по которой ваш подход не работает, заключается в определении </2 : должны быть созданы экземпляры обоих аргументов. итак, если вы хотите реализовать это без использования between/3 , вы должны сделать что-то вроде предложения svick.

Ответ №3:

Используя SWI-Prolog и library(clpfd) , вы можете написать

 :- use_module(library(clpfd)).

foo(X,Low,High) :-
    X #> Low,
    X #< High,
    label([X]).
  

Ответ №4:

Вы также могли бы сделать это (в значительной степени переопределение между / 3:

 range( X , Y , Z ) :-
  integer(X) ,
  integer(Y) ,
  range1(X,Y,Z)
  .

range1( X , X , X ) .              % X equals Y
range1( X , Y , X ) :- X < Y .
range1( X , Y , Z ) :- X < Y , X1 is X 1 , range( X1 , Y , Z ) .
range1( X , Y , X ) :- X > Y .
range1( X , Y , Z ) :- X > Y , X1 is X-1 , range( X1 , Y , Z ) .