[英]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.