简体   繁体   English

序言:列表中的平方数

[英]Prolog: square numbers in a list

Ho do I square numbers in a list in prolog? 如何在序言中对列表中的数字求平方?

The list can contain numbers, atoms and lists. 该列表可以包含数字,原子和列表。

for example: [a,b,2,3,4,[3],[c,d,9]] and the answer should be [a,b,4,9,16,[3],[c,d,9]] . 例如: [a,b,2,3,4,[3],[c,d,9]] ,答案应为[a,b,4,9,16,[3],[c,d,9]] As we see in the answer it should be a shallow squaring of the values in the list. 正如我们在答案中看到的,它应该是列表中值的浅平方。

2->4 2-> 4

3->9 3-> 9

4->16 4-> 16

What I have tried so far, 到目前为止我尝试过的

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

X will contain squared values. X将包含平方值。 Base case is when empty list is received. 基本情况是接收到空列表时。 I check if head (A) is a number then I go ahead square the number and change A to A * A. Then go ahead and call the square function for remaining part B. 我检查(A)头是否为数字,然后对数字求平方,然后将A更改为A *A。然后对其余部分B求平方函数。

Please suggest where I am doing wrong. 请指出我做错了什么。

EDIT: Correct answer as follows. 编辑:正确答案如下。 By aBathologist. 由一名浴学家。 Please read his comment for detailed explanation. 请阅读他的评论以获取详细说明。

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

And

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

We're defining a predicate which describes the relationship between one list, A, and another list, B: B should have all the same elements as A, except that any number in A should be squared in B. 我们正在定义一个谓词,该谓词描述一个列表A和另一个列表B之间的关系:B应该具有与A相同的所有元素,只是A中的任何数字都应在B中平方。

Where you've gone wrong: 您哪里出错了:

  • Your ground condition, square([],X) , says that when A is empty, then B is anything (so, for instance, even something like square([], 15) is true). 您的基本条件square([],X)表示,当A为空时,则B为任意值(例如,即使是square([], 15)也为真)。 But this doesn't capture the meaning we're after, since the second argument should be a list with the same number of members as the first. 但这并没有捕获我们所追求的含义,因为第二个参数应该是与第一个参数具有相同成员数的列表。 That is, when the first list is empty then the second list should be empty. 也就是说,当第一个列表为空时,第二个列表应为空。
  • The same problem occurs with your recursive rule, since, at each iteration, an undetermined variable is passed along, and there is never anything said about the relationship between the first list and the second. 您的递归规则也会出现相同的问题,因为在每次迭代中,都会传递一个不确定的变量,并且关于第一个列表和第二个列表之间的关系永远不会说。
  • This rule will only succeed if the first element of alist is a number. 当alist的第一个元素是数字时,此规则才会成功。 In the case where the first element is, eg, a (like in your example), number(a) will be false. 在第一个元素为a的情况下(例如您的示例), number(a)将为false。 Since there are no additional rules for the predicate, it will simply be false unless every member of the first list is a number. 由于该谓词没有其他规则,因此除非第一个列表的每个成员都是一个数字,否则它将完全为假。
  • Variables in Prolog must always have the same, consistent value throughout the context in which they appear. Prolog中的变量在它们出现的整个上下文中必须始终具有相同的一致值。 They function like variables in arithmetic formula. 它们的作用类似于算术公式中的变量。 The formula a + b - b = a is true for any values of a and b but *only if a and b are each assigned one, consistent value throughout the equation. 公式a + b - b = a对于ab的任何值都是正确 ,但*仅当ab在整个方程式中均被分配一个一致的值时。 The same is true in Prolog statements of the form <variable> is <expression> . 在Prolog语句中, <variable> is <expression>形式也是如此。 What you've written says a = a * a which cannot be the case. 您所写的内容表示a = a * a ,但事实并非如此。

*What you're definition says is, roughly, this: The list B is a squared version of the list A if A is an empty list and B is anything OR if the first element of A is a number, and that number is equal to itself squared, and B is a squared version of the rest of A. *您的定义大致是这样的:如果A是一个空列表,并且B是任何东西,或者如果A的第一个元素是数字,并且该数字等于,则列表B是列表A的平方形式的平方,而B是A其余部分的平方。

Here's one possible solution: 这是一种可能的解决方案:

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

Notice that this definition is able to establish a meaningful relationship between the two lists by having them either share variables, or contain elements related by a chain of relations between variables (ie, SqrdL is related to L by virtue of being L * L). 注意,通过使两个列表共享变量或包含与变量之间的关系链相关的元素,该定义能够在两个列表之间建立有意义的关系(即SqrdL由于为L * L而与L相关)。 This definition has one more clause then yours, which enables it to take account of the members of a list which are not numbers: those are added to the second list unaltered. 这个定义比您的定义多了一个子句,这使它能够考虑不是数字的列表成员:将这些成员不变地添加到第二个列表中。

An alternative definition, using If-Then-Else notation for cleaner expression, would be the following: 使用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)
  ).

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM