gpt4 book ai didi

序言程序 : another way to define a functor

转载 作者:行者123 更新时间:2023-12-01 09:24:52 25 4
gpt4 key购买 nike

在我上次的考试中,我必须根据以下说明编写一个名为 double/2 的 Prolog 谓词:double(X, Y) 应该为 true if Y 是一个与 X 长度相同的整数列表,其中每个偶数的 X 都被替换为其 double 。因此,例如,查询 double([1, 3, 2, 4], X).应该结果 X = [1, 3, 4, 8]。

为了简单起见,我被允许使用仿函数 even/1,而无需定义它(实际上很容易定义它),当参数为偶数时为真,当参数为偶数时为假否则。实际上,我最终也使用仿函数 odd/1 编写了程序。但我的教授告诉我:“你可以只用偶数来写,没必要用奇数!”所以我想知道我怎么能这样写。

我写的是以下内容:

double([], []).
double([N|L], [N|D]) :- odd(N), !, double(L, D).
double([N|L], [M|D]) :- even(N), M is 2*N, double(L, D).

备注:如果我从最后一行代码中删除 even(N)(所以如果我只使用 odd(N),这实际上与使用相同只有 even(N),因为我只使用其中一个),那么程序仍然可以工作。但这不是一个理想的解决方案,因为这样“剪切”变成了红色剪切(在我的程序中它是绿色剪切)。

最佳答案

如果您只是对正确的解决方案感兴趣,请采用@PauloMoura 的解决方案。这就是我认为这个练习的目的。以您的原始程序为例,(乍一看)似乎可以删除第二个子句中的目标 even(N)

但在此之前,让我明确一点,谓词名称 doubles/2 是用词不当。我宁愿说 list_semidoubled/2...

odd(N) :-   N mod 2 =:= 1.double([], []).double([N|L], [N|D]) :-   odd(N), !, double(L, D).double([N|L], [M|D]) :-   % even(N),   M is 2*N, double(L, D).

However, the cut above does a little bit more than we expected. It does not cut when odd(N) is true alone, but there is a tiny little extra condition that sneaked into our program. Do you see it? Let's have a look at the relevant part:

double([N|L], [N|D]) :-
odd(N), !, ...

odd(N),但是看上面!在头脑中,另一种情况正在那里。它一直等到它可以造成严重破坏! “隐藏”的条件是:

If N is equal (unifies) to the first element in the second argument!

让我们试试吧!

?- double([1], Xs).
Xs = [1].

Worx 正如预期的那样,不是吗。然而:

?- double([1], [2]).
true.

天狮,这里发生了什么?那应该会失败!

以这种方式表现的谓词缺乏坚定性。我们预计查询会失败,因为 Prolog 没有向我们展示这个解决方案。

所以上面的剪裁并不总是像你预期的那样剪裁,但比你预期的要少一点。这些错误通常很难找到,因此最好从一开始就避免它们。您有多种选择:

1 坚持纯粹、单调的 Prolog

这可能是初学者的最佳选择。而且它不一定效率较低。我宁愿:

double(Xs, Ys) :
maplist(n_semidoubled, Xs, Ys).

n_semidoubled(X, Y) :-
M is X mod 2,
( M = 0,
Y is X*2
; M = 1,
Y is X
).

这可以改进为 - 有点骇人听闻:

 n_semidoubled(X, Y) :-
Y is X*(2-X mod 2).

2 使用 (\+)/1, once/1, if-then-else

@PaulMoura 已经向您展示了一种这样的可能性。另一种是使用 (\+)/1:

n_semidoubled(X, X) :-
odd(X).
n_semidoubled(X, Y) :-
\+odd(X),
Y is X*2.

3 缩小切割范围

如果您现在仍决定使用此构造,请尝试重新构建您的程序,使剪切的范围尽可能地局部化。也就是说,与其将切割放在递归规则中,不如做一个局部谓词:

doubles([], []).
doubles([E|Es], [M|Ms]) :-
n_semidoubled(E, M),
doubles(Es, Ms).

n_semidoubled(E, M) :-
odd(E),
!,
M is E.
n_semidoubled(E, M) :-
M is E*2.

您的原始程序中还有另一个与剪辑问题无关的异常情况。考虑:

?- double([1*1],Xs).
Xs = [1*1].

关于序言程序 : another way to define a functor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26938380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com