(SWI-PL)我不知道如何创建一个序言规则来匹配这种特定类型的输入

问题描述 投票:1回答:1

所以我有一个家庭作业,在其中给出了以下代码:

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).

现在,以上代码对于提供的前3个输入非常有效。我很难去考虑序言可能如何解释最后一个,以及如何利用它。

这就是我想的可能的工作。

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作为我的序言分发。

prolog swi-prolog logic-programming
1个回答
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).
© www.soinside.com 2019 - 2024. All rights reserved.