Я плохо знаком с Прологом. Я должен записать целочисленный сумматор, который добавит числа между 0-9 к другим номерам 0-9 и произведет решение 0-18. Это - то, что я хочу сделать:
% pseudo code
add(in1, in2, out) :-
in1 < 10,
in2 < 10,
out < 18.
Я хотел бы смочь назвать его как это:
Чтобы проверить, является ли это допустимое дополнение:
?- add(1,2,3).
true.
?- add(1,2,4).
false.
С одной отсутствующей переменной:
?- add(X,2,3).
X = 1.
?- add(1,4,X).
X = 5.
С несколькими отсутствующими переменными:
?- add(X,Y,Z).
% Some output that would make sense. Some examples could be:
X=1, Y=1, Z=2 ;
X=2, Y=1, Z=3 ......
Я понимаю, что это - вероятно, довольно упрощенный вопрос, и это, вероятно, очень просто. Однако согласно учебному руководству по Прологу я использую:
"В отличие от Arithmetic Comparison Operators объединения операторы не могут использоваться для предоставления значений переменной. Банка только быть оцененным, когда каждый термин на каждой стороне были инстанцированы".
Решение:
lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
addSimple(Add1,Add2,Sol) :-
lessThanTen(Add1),
lessThanTen(Add2),
Sol is Add1+Add2.
Все современные системы Prolog предоставляют ограничения конечной области, которые являются истинными отношениями, которые могут (в отличие от более низкоуровневых арифметических предикатов, таких как is/2 и >/2) использоваться во всех направлениях. В SWI-Prolog:
:- use_module(library(clpfd)).
plus(X, Y, Z) :-
[X,Y] ins 0..9,
X + Y #= Z.
Результаты для ваших примеров:
?- plus(1,2,3).
true.
?- plus(1,2,4).
false.
?- plus(X,2,3).
X = 1.
?- plus(1,4,X).
X = 5.
?- plus(X,Y,Z).
X in 0..9,
X+Y#=Z,
Y in 0..9,
Z in 0..18.
Поскольку предикат может использоваться во всех направлениях, больше не имеет смысла называть его "add/3", поскольку это подразумевает направление, но предикат действительно описывает, когда отношение выполняется, и поэтому является более общим.
Что насчет этого? :
add(X,Y,Z) :-
Z is X + Y,
X < 10,
Y < 10,
Z < 19.
Проблема: это хорошо работает для запросов вида add(1,1,X)
, потому что Z
инстанцируется перед вызовами <
, но не работает, когда вы спрашиваете add(X,1,2)
. Можно использовать var/1
для различения типа запроса (var/1
сообщает, является ли переменная неинстанцированной или нет), но это звучит очень мучительно.