Prolog:列表中的方形数字

时间:2013-11-02 19:32:06

标签: list recursion prolog

我可以在prolog的列表中对数字进行平方吗?

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

例如:[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将包含平方值。基本情况是收到空列表。我检查头部(A)是否是数字然后我继续将数字平方并将A改为A * A.然后继续调用方形函数以保留B部分。

请说明我做错了。

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

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

1 个答案:

答案 0 :(得分:3)

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

你出错的地方:

  • 你的基础条件square([],X)表示当A为空时,B就是任何东西(例如,甚至类似square([], 15)的东西都是真的)。但这并没有捕捉到我们所追求的含义,因为第二个参数应该是一个与第一个参数数量相同的列表。也就是说,当第一个列表为空时,第二个列表应为空。
  • 您的递归规则也会出现同样的问题,因为在每次迭代时,都会传递一个未确定的变量,并且从来没有任何关于第一个列表和第二个列表之间关系的说法。
  • 如果alist的第一个元素是数字,则此规则成功。在第一个元素是例如a的情况下(如示例所示),number(a)将为false。由于谓词没有附加规则,除非第一个列表中的每个成员都是数字,否则它将是假的。
  • Prolog中的变量必须始终在它们出现的上下文中具有相同的一致值。它们像算术公式中的变量一样运行。对于 a a + b - b = a 为true >和 b 但*仅当 a b 在整个等式中分配一个一致的值时。形式为<variable> is <expression>的Prolog语句也是如此。你写的是 a = a * a ,但情况并非如此。

*您所定义的内容大致是这样的:列表B是列表A的平方版本,如果A是空列表而B是任何OR,如果A的第一个元素是数字,那么number等于其自身的平方,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)
  ).