2

我如何在序言的列表中对数字进行平方?

列表可以包含数字、原子和列表。

例如:[a,b,2,3,4,[3],[c,d,9]]答案应该是[a,b,4,9,16,[3],[c,d,9]]。正如我们在答案中看到的那样,它应该是列表中值的浅平方。

2->4

3->9

4->16

到目前为止我所尝试的,

square([],X).
square([A|B],X):-number(A), A is A*A, square(B,X).

X 将包含平方值。基本情况是收到空列表时。我检查 head (A) 是否是一个数字,然后我继续对数字进行平方并将 A 更改为 A * A。然后继续调用剩余部分 B 的 square 函数。

请建议我在哪里做错了。

编辑:正确答案如下。由一位病理学家。请阅读他的评论以获取详细说明。

squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
    number(L),
    SqrdL is L * L,
    squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
    \+number(L),
    squared_members(Ls, SqrdLs).

squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
  ( number(L)
  ->  M is L * L, squared_members(Ls, Ms)  
  ;   M = L, squared_members(Ls, Ms)
  ).
4

1 回答 1

3

我们正在定义一个谓词来描述一个列表 A 和另一个列表 B 之间的关系:B 应该与 A 具有所有相同的元素,除了 A 中的任何数字都应该在 B 中平方。

你哪里出错了:

  • 您的基本条件square([],X)表示,当 A 为空时,B 是任何东西(例如,即使类似的东西square([], 15)也是真的)。但这并没有捕捉到我们要表达的意思,因为第二个参数应该是一个与第一个参数数量相同的列表。也就是说,当第一个列表为空时,第二个列表应该为空。
  • 您的递归规则也会出现同样的问题,因为在每次迭代中,都会传递一个未确定的变量,并且从来没有说过第一个列表和第二个列表之间的关系。
  • 只有当 alist 的第一个元素是数字时,此规则才会成功。在第一个元素的情况下,例如a(如您的示例中),number(a)将是错误的。由于谓词没有其他规则,除非第一个列表的每个成员都是数字,否则它只会是错误的。
  • Prolog 中的变量在它们出现的上下文中必须始终具有相同、一致的值。它们的功能类似于算术公式中的变量。公式a + b - b = a对于ab的任何值都是正确的,但*仅当ab都被分配一个时,整个方程中的值一致。在 Prolog 形式的语句中也是如此<variable> is <expression>。您所写的内容是a = a * a,但事实并非如此。

*您的定义大致是这样的:如果 A 是空列表并且 B 是任何东西,或者如果 A 的第一个元素是数字,并且该数字相等,则列表 B 是列表 A 的平方版本自身平方,B 是 A 其余部分的平方版本。

这是一种可能的解决方案:

squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
    number(L),
    SqrdL is L * L,
    squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
    \+number(L),
    squared_members(Ls, SqrdLs).

请注意,此定义能够通过使两个列表共享变量或包含由变量之间的关系链相关的元素(即,SqrdL 与 L 的关系为 L * L)来在两个列表之间建立有意义的关系。这个定义比你的多了一个子句,这使它能够考虑列表中不是数字的成员:这些成员原封不动地添加到第二个列表中。

使用 If-Then-Else 表示法进行更简洁的表达的替代定义如下:

squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
  ( number(L)
  ->  M is L * L, squared_members(Ls, Ms)  
  ;   M = L, squared_members(Ls, Ms)
  ).
于 2013-11-03T00:34:33.753 回答