2013-04-21 147 views
1

我是新來的Prolog,我似乎無法自己得到這個答案。只計算數字和字母列表中的數字

我想要的是,Prolog統計列表中的數字,而不是每個元素。因此,例如:

getnumbers([1, 2, c, h, 4], X). 

應該給我:

X=3 

getnumbers([], 0). 
getnumbers([_ | T], N) :- getnumbers(T, N1), N is N1+1. 

是我得到了什麼,但它顯然給了我在列表中的每個元素。我不知道如何以及在哪裏放一個「只計數」。

回答

1

考慮使用內置的謂詞(例如,在SWI-Prolog的),並檢查它們的實現,如果你有興趣在如何做到這一點吧:

include(number, List, Ns), length(Ns, N)

+0

啊我看,這工作得非常好。謝謝,但是,如果我想避免使用內置的謂詞,你能指出我正確的方向嗎?就像在現有代碼中實現「只使用數字」一樣。從我看到的情況看來,只有在諮詢序言的時候,你可以使用數字/ 1,這是真的嗎? – Majusbeh 2013-04-21 16:49:11

0
當然

,必須檢查要查看它是否滿足條件的元素的類型。

number/1這是你正在尋找的謂詞。

另請參見if/then/else構造,用於遞歸子句。

0

這裏使用的Prolog的自然圖案數/ 1的匹配,以及附加條款(下面3)處理不是數字的情況。

% 1 - base recursion 
getnumbers([], 0). 

% 2 - will pass ONLY if H is a number 
getnumbers([H | T], N) :- 
    number(H), 
    getnumbers(T, N1), 
    N is N1+1. 

% 3 - if got here, H CANNOT be a number, ignore head, N is unchanged, recurse tail 
getnumbers([_ | T], N) :- 
    getnumbers(T, N). 
+0

如果head *是一個數字,第三個子句也匹配。 – mat 2013-04-22 13:43:22

+0

不明白墊子。如果head是一個數字,它將被第二條規則所捕獲,所以第三條規則永遠不會達到,因爲3條款將按1..2..3的順序執行,或者我錯過了什麼? – magus 2013-04-22 17:01:54

+0

如果head是一個數字,則適用第二條和第三條規則。由於回溯,兩者都將被嘗試,並且按照該順序進行。你是否在'? - getnumbers([1])上試過這個程序。'? – mat 2013-04-23 07:48:06

0

一個共同的序言成語有這種問題是先定義你的斷言對於大衆消費,並把它調用一個「工人」謂詞。通常它會使用某種累加器。對於您的問題,市民的消費謂詞是一樣的東西:

count_numbers(Xs , N) :- 
    count_numbers_in_list(Xs , 0 , N) . 

count_numbers_in_list([] , N , N) . 
count_numbers_in_list([X|Xs] , T , N) :- 
    number(X) , 
    T1 is T+1 , 
    count_numbers_in_list(Xs , T1 , N) 
    . 

您將要構建的遞歸位,所以它是尾遞歸爲好,這意味着遞歸調用取決於什麼,但在數據參數列表。這允許編譯器在每次調用時重用現有的堆棧框架,所以謂詞實際上是迭代的,而不是遞歸的。正確的尾遞歸謂詞可以處理無限長度的列表;一個不會在每次遞歸時分配一個新的堆棧幀並最終放棄它的堆棧。以上count_numbers_in_list/3是尾遞歸。這不是:

getnumbers([H | T], N) :- 
    number(H), 
    getnumbers(T, N1), 
    N is N1+1. 
1

保持邏輯上純,很容易:使用元謂詞 tcount/3亦隨物化型測試謂詞number_t/2(簡稱number_truth/2):

number_t(X,Truth) :- number(X), !, Truth = true. 
number_t(X,Truth) :- nonvar(X), !, Truth = false. 
number_t(X,true) :- freeze(X, number(X)). 
number_t(X,false) :- freeze(X,\+number(X)). 

讓我們運行查詢OP建議:

 
?- tcount(number_t,[1,2,c,h,4],N). 
N = 3.          % succeeds deterministically 

請注意,這是單調的:延遲變量綁定總是l聽起來很健康。試想一下:

 
?- tcount(number_t,[A,B,C,D,E],N), A=1, B=2, C=c, D=h, E=4. 
N = 3, A = 1, B = 2, C = c, D = h, E = 4 ; % succeeds, but leaves choice point 
false. 

最後,讓我們看一些下面相當一般查詢的答案:

?- tcount(number_t,[A,B,C],N). 
N = 3, freeze(A, number(A)), freeze(B, number(B)), freeze(C, number(C)) ; 
N = 2, freeze(A, number(A)), freeze(B, number(B)), freeze(C,\+number(C)) ; 
N = 2, freeze(A, number(A)), freeze(B,\+number(B)), freeze(C, number(C)) ; 
N = 1, freeze(A, number(A)), freeze(B,\+number(B)), freeze(C,\+number(C)) ; 
N = 2, freeze(A,\+number(A)), freeze(B, number(B)), freeze(C, number(C)) ; 
N = 1, freeze(A,\+number(A)), freeze(B, number(B)), freeze(C,\+number(C)) ; 
N = 1, freeze(A,\+number(A)), freeze(B,\+number(B)), freeze(C, number(C)) ; 
N = 0, freeze(A,\+number(A)), freeze(B,\+number(B)), freeze(C,\+number(C)). 
+0

理想情況下'number/1'的測試,'atom/1'由一個明確的'nonvar/1' **保護,就好像它們會產生實例化錯誤一樣。 – false 2015-06-16 09:19:51