我是prolog的新手并且正在尝试创建一个可以给出的二元谓词 所有数字均为平方的列表,包括子列表中的数字。 e.g。
?-dcountSublists([a,[[3]],b,4,c(5),4],C).
C=[a,[[9]],b,c(5),16]
任何人都可以指导我如何做到这一点。 谢谢。感谢使用片段回答
答案 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].
请注意,如果输入术语有数字,则会失败,因为它没有用于识别和处理它们的谓词。我会留给你的。
祝你好运!