(SWI-PL) Я не могу понять, как создать правило пролога для соответствия этому конкретному типу ввода

Итак, у меня есть домашнее задание, в котором я дал следующий код:

numeral(0).
numeral(succ(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).

add(0,X,X).
add(succ(X),Y,succ(Z)) :- add(X,Y,Z).

И я должен определить предикат пролога add2 (X, Y, Z), который будет производить, например, следующие выходные данные

% Exercise 1 Test Cases (for copy-paste to the REPL
%% 1. add2(succ(0)+succ(succ(0)), succ(succ(0)), Z).
%%    >>>> Z = succ(succ(succ(succ(succ(0)))))
%%
%% 2. add2(0, succ(0)+succ(succ(0)), Z).
%%    >>>> Z = succ(succ(succ(0)))
%%
%% 3. add2(succ(succ(0)), succ(0)+succ(succ(0)), Z).
%%    >>>> Z = succ(succ(succ(succ(succ(0)))).
%%
%% 4. add2(succ(0)+succ(0), succ(0+succ(succ(0))), Z).
%%    >>>> Z = succ(succ(succ(succ(succ(0))))).

Итак, я работал над этим последние несколько дней и предпринял разумную попытку найти решение. Вот что я до сих пор пытался:

% Exercise 1 Solution
add2(X,Y,Z):- add(X,Y,Z).
add2(A+B,Y,Z):- add2(A,B,X), add2(X,Y,Z).
add2(X,A+B,Z):- add2(A,B,Y), add2(X,Y,Z).

Теперь этот приведенный выше код довольно хорошо работает для первых трех предоставленных входных данных. Мне трудно думать о том, как пролог может интерпретировать последнее и как я могу этим воспользоваться.

Вот то, что я подумал, может сработать.

add2(X, succ(A+B), Z):- add2(A,B,Y), add2(X, succ(Y), Z).

Я думал, что интерпретатор распознает ввод, такой как succ (0 + succ (...)) как succ (A + B), и тогда приведенные выше правила смогут разрешить 0 + succ (. ..) в succ (...). Результат, который я получаю от SWI-PL REPL, прост:

Z = succ(succ(succ(0+succ(succ(0))))) 

Еще одна попытка, которую я предпринял, заключалась в следующем:

add2(X,succ(0+succ(Y), Z)):- add2(X,succ(Y),Z).

Однако это дает тот же результат, что и раньше. Я не уверен, почему две вышеупомянутые попытки, похоже, не работают для меня, и хотя я делал другие предположения, были более или менее случайные вариации двух вышеупомянутых или других предикатов, и если бы я преуспел с помощью этого подхода, я бы вероятно, получил правильный ответ, не понимая, что я делал.

Я использую SWI-PL в качестве своего пролога.


person Eoin Dowling    schedule 12.10.2019    source источник


Ответы (1)


Я думаю, что это может помочь решить проблему, используя здесь вспомогательный предикат. Вспомогательная функция преобразует число, представленное каскадом succ(…) и … + …, в единый стиль (то есть только succ(…)).

Таким образом, мы можем реализовать такую ​​функцию, как:

normsucc(0, 0).
normsucc(succ(X), succ(NX)) :-
    normsucc(X, NX).
normsucc(X+Y, NXY) :-
    normsucc(X, NX),
    normsucc(Y, NY),
    add(NX, NY, NXY).

Итак, мы можем использовать normsucc для вычисления суммы:

add2(X, Y, Z) :-
    normsucc(X, NX),
    normsucc(Y, NY),
    add(NX, NY, Z).

или проще, например @ false предлагает:

add2(X, Y, Z) :-
    normsucc(X+Y, Z).
person Willem Van Onsem    schedule 12.10.2019
comment
Почему бы и нет: add2(X, Y, Z) :- normsucc(X+Y, Z). - person false; 13.10.2019