二元谓词到方格列表和Prolog中的子列表

时间:2011-11-08 01:46:50

标签: prolog

我是prolog的新手并且正在尝试创建一个可以给出的二元谓词  所有数字均为平方的列表,包括子列表中的数字。     e.g。

?-dcountSublists([a,[[3]],b,4,c(5),4],C).
  C=[a,[[9]],b,c(5),16]

任何人都可以指导我如何做到这一点。 谢谢。感谢使用片段回答

2 个答案:

答案 0 :(得分:0)

SWI-Prolog具有谓词{{​​3}},允许您在某些列表上映射谓词。 使用它,您只需要创建一个谓词,它将对一个数字或列表中的数字进行平方,并保留其他所有内容。谓词number / 1,is_list / 1如果参数是数字或列表,则为真。

因此:

    square(N,NN):-
            integer(N),
            NN is N*N.

    square(L,LL):-
            is_list(L),
            dcountSublists(square,L,LL).

    square(Other,Other):-
            \+ number(Other),
            \+ is_list(Other).

    dcountSublists(L,LSquared):-
            maplist(square,L,LSquared).

在最终谓词中否定我们避免多个(错误的)解决方案: 例如,dcountSublists([2],X)将返回X=[4]X=[2]。 如果我们使用广场or once/1的if-then-else结构来调用square/2,则可以避免这种情况。

如果这是家庭作业,也许你不应该使用maplist,因为(可能)练习的目的是学习如何建立一个递归函数;无论如何,我建议尝试编写一个没有maplist的等效谓词。

答案 1 :(得分:0)

使用Prolog中的递归很容易实现。请记住,Prolog中的所有内容都是变量或术语(原子只是0-arity术语),所以术语如下所示:

[a,[[3]],b,4,c(5),4]

...很容易被解构(还要注意列表语法[..]是二元谓词./2的糖)。 Prolog提供了一系列谓词来测试特定类型的术语,例如数字,字符串或复合术语(例如compound/1)。

要构建您所追求的谓词,我建议使用以下几个谓词来编写它:

dcountSublists(In, Out) :-
  % analyze type of In
  % based on type, either: 
  %   1. split term into subterms for recursive processing
  %   2. term cannot be split; either replace it, or pass it through

这是一个让你开始的例子。以下内容识别复合词,并使用术语de / constructor =../2将它们分开:

dcountSublists(In, Out) :-
  % test if In has type compound term
  compound(In),
  % cut to exclude backtracking to other cases below this predicate
  !, 
  % deconstruct In into functor and an argument list
  In =.. [Func|Args],
  % apply dcountSublists/2 to every argument, building new args
  maplist(dcountSublists, Args, NewArgs),
  % re-construct In using the new arguments
  Out =.. [Func|NewArgs].

dcountSublists(In, Out) :-
  % test if In has type atom
  atom(In), !, 
  % pass it through
  Out = In.

测试:

?- dcountSublists([a,[[e]],b,a,c(s),a], L).
L = [a, [[e]], b, a, c(s), a].

请注意,如果输入术语有数字,则会失败,因为它没有用于识别和处理它们的谓词。我会留给你的。

祝你好运!