2015-11-27 41 views
1

我想在Prolog中爲每個找到的數字構造一個列表。例如,findNumber([g,o,o,d,j,0,6],[0,6]),但我不能給定的代碼構建列表:列出在Prolog列表中找到的數字

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). 

請幫助...我是相當的鹹菜。謝謝!

+1

幾乎:' - 包括(數字,並[g,鄰,鄰,d,J,0,6],NS).' – CapelliC

+0

@CapelliC如何?我是否要做一個列表清單,如果我有,例如。 [[g,o,o,d],[6,0,0,d]] => [6,0,0]?是否有可能爲多個列表做? – Tyler

回答

2

有幾個問題與您的代碼:

您使用謂詞isNum自己定義的,但只有6似乎是一個數字。 0是不是一個數字?所以糾正這種給:

isNum(0). 
isNum(6). 

或使用的內置謂詞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). 

或者您也可以通過使用切(!)使謂詞更緊湊(和更快一點):

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/2findNumber/3轉換完成的操作。

存在這樣的Prolog會懷疑是否有子列表(第二條),它會調用findNumber/3與列表findNumber(H,TA,TL)的頭,會生成一個列表TA不留尾巴TL開放的一個特例。新的尾巴TL將比後來填寫呼叫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]. 
+0

你如何改變列表的列表?所以,如果你有一個列表,例如。 [[g,o,o,d],[6,0,0,d]] => [6,0,0]。我如何得到以下內容? – Tyler

+0

@Tyler:你的意思是遞歸的嗎?還是等級數目限制爲'2'? –

+0

我的意思是遞歸直到列表中的列表用完了。所以當,例如。 [[g,o,0,d],[w,1,l,1]]作爲輸入傳遞,它將查找列表中每個列表的所有編號,直到不再有列表爲止。因此,它將打印一個列表[0,1,1]。 – Tyler