[英]Make a list of numbers found in list in Prolog
我正在尝试在Prolog中为找到的每个号码构建一个列表。 例如, findNumber([g,o,o,d,j,0,6],[0,6])
,但是我无法使用给定的代码构造列表:
isNum(6).
isNum(6).
findNumber([],[]).
findNumber([V|T],[-|TAfter]) :-
isNum(V),
findNumber(T,TAfter).
findNumber([H|T],[H|TAfter]) :-
not(isNum(H)),
findNumber(T,TAfter).
请帮忙...我很腌。 谢谢!
您的代码存在一些问题:
您使用谓词isNum
定义自己,但似乎只有6
个数字。 0
不是数字吗? 因此,请更正为:
isNum(0).
isNum(6).
或使用swi-prolog的内置谓词number/1
。 (使用number/1
想法会稍微修改语义,因为number/1
不会实例化给定的变量;只要您仅在一个方向上使用谓词-从列表到子列表-且不使用未实例化的变量,那很好)。
其次,谓词本身。 首先,您以某种方式交换了大小写:在这里它将H
添加到第三子句中的结果列表中(其中H
不是数字)。 此外,在第二个子句中,您在列表中添加了破折号( -
)(这似乎不是所希望的行为)。 因此,更好的谓词可能是:
findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
number(H),
findNumber(T,TAfter).
findNumber([H|T],TAfter):-
not(number(H)),
findNumber(T,TAfter).
或者,您可以使用cut( !
)使谓词更紧凑(并且更快一点):
findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
number(H),
!,
findNumber(T,TAfter).
findNumber([_|T],TAfter):-
findNumber(T,TAfter).
演示( swipl
):
?- findNumber([g,o,o,d,j,0,6],X).
X = [0, 6].
?- findNumber([g,o,0,o,d,j,6],X).
X = [0, 6].
如果您要递归执行此操作,可以通过将谓词扩展为三个参数版本findNumber/3
来执行此操作。 首先,我们在findNumber/3
上使用两个参数findNumber/2
映射版本:
findNumber(A,B) :-
findNumber(A,B,[]).
(应删除先前定义的谓词)。
接下来,我们定义以下子句:
findNumber([],TT,TT).
findNumber([H|T],[H|TA],TT) :-
number(H),
!,
findNumber(T,TA,TT).
findNumber([H|T],TA,TT):-
findNumber(H,TA,TL),
!,
findNumber(T,TL,TT).
findNumber([_|T],TA,TT) :-
findNumber(T,TA,TT).
这与称为差异列表的技术一起使用,该技术将在内存和CPU效率方面相当高。 此外,调用堆栈只会增加给定列表的级别数。
第三个参数指定应将哪个值放在列表的末尾。 显然,基本情况是列表应该以[]
结尾(这就是我们使用findNumber/2
到findNumber/3
转换。
在特殊情况下,Prolog会怀疑是否存在子列表(第二个子句),它将以列表findNumber(H,TA,TL)
的开头调用findNumber/3
,并生成列表TA
尾TL
打开。 新的尾部TL
随后将被一个调用findNumber(H,TL,TT)
填充(因此findNumber(H,TL,TT)
我们会将原始的尾部TT
放在真实的后面,但需要一个中间尾部TL
)。
演示( swipl
) :
?- findNumber([[g,0,0,d],[n,4,s,t,y]],K).
K = [0, 0, 4].
?- findNumber([[g,0,0,d],[n,4,[s,3,9],t,y]],K).
K = [0, 0, 4, 3, 9].
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.