[英]Make a list of numbers found in list in Prolog
I am trying to construct a list in Prolog for every number it has found. 我正在尝试在Prolog中为找到的每个号码构建一个列表。 For example,
findNumber([g,o,o,d,j,0,6],[0,6])
, but I can't construct the list with the given code: 例如,
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).
Please help... I am in quite the pickle. 请帮忙...我很腌。 Thank you!
谢谢!
There are a few problems with your code: 您的代码存在一些问题:
You use a predicate isNum
you define yourself, but only 6
seems to be a number. 您使用谓词
isNum
定义自己,但似乎只有6
个数字。 0
is not a number? 0
不是数字吗? So correct this to: 因此,请更正为:
isNum(0).
isNum(6).
or use swi-prolog 's builtin predicate number/1
. 或使用swi-prolog的内置谓词
number/1
。 (mind using number/1
slightly modifies the semantics since number/1
does not instantiate the given variable; as long as you use the predicate in only one direction - list to sublist - and do not use uninstantiated variables, that's fine however). (使用
number/1
想法会稍微修改语义,因为number/1
不会实例化给定的变量;只要您仅在一个方向上使用谓词-从列表到子列表-且不使用未实例化的变量,那很好)。
Secondly the predicate itself. 其次,谓词本身。 First of all, you somehow swapped the cases: here it will add the
H
to the resulting list in the third clause (where H
is not a number). 首先,您以某种方式交换了大小写:在这里它将
H
添加到第三子句中的结果列表中(其中H
不是数字)。 Furthermore in the second clause you add a dash ( -
) to the list (this does not seem to be the desired behavior). 此外,在第二个子句中,您在列表中添加了破折号(
-
)(这似乎不是所希望的行为)。 A better predicate is therefore probably: 因此,更好的谓词可能是:
findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
number(H),
findNumber(T,TAfter).
findNumber([H|T],TAfter):-
not(number(H)),
findNumber(T,TAfter).
Or you can make the predicate more compact (and a bit faster) by using a cut ( !
): 或者,您可以使用cut(
!
)使谓词更紧凑(并且更快一点):
findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
number(H),
!,
findNumber(T,TAfter).
findNumber([_|T],TAfter):-
findNumber(T,TAfter).
Demo ( swipl
): 演示(
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].
In case you want to do this recursively, you could do this by extending the predicate to a three arguments version findNumber/3
. 如果您要递归执行此操作,可以通过将谓词扩展为三个参数版本
findNumber/3
来执行此操作。 First we map the version with two arguments findNumber/2
on findNumber/3
: 首先,我们在
findNumber/3
上使用两个参数findNumber/2
映射版本:
findNumber(A,B) :-
findNumber(A,B,[]).
(the previously defined predicate should be removed). (应删除先前定义的谓词)。
Next we define the following clauses: 接下来,我们定义以下子句:
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).
This works with a technique called difference lists which will be rather memory and cpu efficient. 这与称为差异列表的技术一起使用,该技术将在内存和CPU效率方面相当高。 Furthermore the call stack will only grow in the number of levels of the given list.
此外,调用堆栈只会增加给定列表的级别数。
The third argument specifies which value should be put at the tail of the list. 第三个参数指定应将哪个值放在列表的末尾。 Evidently the base case is that the list should end with a
[]
(that's what we do with the findNumber/2
to findNumber/3
conversion. 显然,基本情况是列表应该以
[]
结尾(这就是我们使用findNumber/2
到findNumber/3
转换。
There is a special case in which Prolog will wonder whether there is a sublist (the second clause), it will call findNumber/3
with the head of the list findNumber(H,TA,TL)
and will generate a list TA
leaving the tail TL
open. 在特殊情况下,Prolog会怀疑是否存在子列表(第二个子句),它将以列表
findNumber(H,TA,TL)
的开头调用findNumber/3
,并生成列表TA
尾TL
打开。 The new tail TL
will than later be filled with a call findNumber(H,TL,TT)
(we thus will put our original tail TT
at the real back, but need an intermediate tail TL
). 新的尾部
TL
随后将被一个调用findNumber(H,TL,TT)
填充(因此findNumber(H,TL,TT)
我们会将原始的尾部TT
放在真实的后面,但需要一个中间尾部TL
)。
Demo ( swipl
) : 演示(
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.