1

我对 Prolog 完全陌生,正在做家庭作业。我的程序应该采用两个长度相等的列表,并执行 D = sqrt((X1-Y1)^2 + (X2-Y2)^2 + ... + (XN-YN)^2)。我已经编写了代码来获得正确的答案,但它没有正确呈现它。我认为这可能是逻辑流程的问题,因为它似乎以无限循环结束。它应该看起来像:

?- distance([1,2,3], [2,3,4], D).
D = 1.732051.

我的代码给了我正确的结果,但它的打印结果如下:

?- distance([1,2,3],[2,3,4],D).
1.732051
true

只是因为我在那里有一行来打印结果。在我按下回车键之前它也不会结束(没有句点),这就是为什么我担心我有一个循环。如何改写我的代码或重定向我的逻辑,以使其正常打印?

distance([],[],D) :-
  F is sqrt(D),
  format("~f~n", [F]).

distance([A|T1], [B|T2], D) :-
  var(D),
  S is (A-B)*(A-B),
  distance(T1, T2, S);
  C is A-B,
  E is C*C,
  F is D+E,
  distance(T1, T2, F).
4

3 回答 3

2

您的程序不会进入无限循环,否则您很可能会在某些时候遇到堆栈溢出错误。发生的事情是您的代码留下了一个开放的选择点,因此最终解释器尝试重做(不成功)。您没有得到预期的结果,因为调用过程中使用的变量 D 永远不会被绑定。

您最好考虑如何递归地建模它来解决这个问题。在这种情况下,您可以例如在输入列表为空时拆分问题,而当它们不是时(我在这里假设使用空列表调用您的过程将产生 0 结果)。

因此,在这种情况下,您将创建两个子句,一个用于基本情况(空列表),另一个用于递归步骤。我还将使用 prolog 中使用的一种常用方法,该方法包括使用累加器。

因此,我们为 distance/3 创建了一个事实,它将调用另一个使用此累加器的过程:

distance(L1,L2,F) :-
    distance(L1, L2, 0, F).

我们使用累加器在您的代码中保存项目差异平方和 (AB)*(AB) 的部分结果:

现在我们从基本情况(空列表)开始:

distance([],[],S,F) :-
  F is sqrt(S).

在这里,我们声明当没有更多项目时的结果是累加器的平方根。

我们现在跟随递归步骤,计算每个列表中第一项的平方项差异并进行递归。

distance([A|T1], [B|T2], D, SQRT) :-
  S is D+(A-B)*(A-B),
  distance(T1, T2, S, SQRT).

现在我们完成了:

?- distance([1,2,3],[2,3,4],D).
D = 1.7320508075688772.
于 2012-04-16T22:09:32.210 回答
0

我不明白该format功能的使用,所以我所能做的就是提供我自己的尝试。我认为您的尝试有一个缺点,即在递归的基本情况方面没有明确说明。

考虑以下我的方法:

distance([],[],0).
distance([A],[A],0).
distance([A|T1],[B|T2],D) :-
    distance(T1,T2,F),
    D is sqrt((A-B)*(A-B) + F*F).
于 2012-04-16T22:09:45.147 回答
0

我认为你应该使用累加器:

distance(L1, L2, D) :- 
    distance(L1, L2, 0, D).

distance([], [], TT, D) :-
    D is sqrt(D).

distance([X1 | Y1], [X2 | Y2], TT, D) :-
    TT1 is TT + (X1 - X2) * X1 - X2),
    distance(Y1, Y2, TT1, D).
于 2012-04-16T22:11:36.400 回答