2012-08-12 23 views
4

我想算一個元素有多少次出現在列表中的特定元素的數量,到目前爲止,我還與計數在序言名單

rate(X,[H|T],N):- 
    X == H, 
    N is N+1, 
    rate(X,T,N). 
rate(X,[_|T],N) :- 
    rate(X,T,N). 
rate(_,[],N) :- 
    N is 0. 

來到了我已經介紹了當一個找到匹配項,當沒有匹配項並且到達列表末尾時。但是,當我測試我得到

43 ?- rate(4,[4,2,3,4,4,2],X). 
ERROR: is/2: Arguments are not sufficiently instantiated 
Exception: (6) frequency(4, [4, 2, 3, 4, 4, 2], _G393) ?  

什麼參數我精確缺失?

回答

4

當且僅當X是數字時,您可以使用is/2(如N is X)。如果X是一個自由變量,則不能使用is/2。在你的第一個條款中你有:N is N+1。這是不好的,因爲N是一個自由變量(它在這一點上沒有值,所以對於N + 1也是如此)。

還有一個錯誤。在:

rate(X,[_|T],N) :- 
    rate(X,T,N). 

因爲你使用這個只有當X不是列表中的第一個元素,你應該檢查這是真的!下面的代碼:

count(_, [], 0) :- !. /* empty list, base case */ 

count(X, [X|T], N) :- /* if X is in the head of the list */ 
    count(X, T, N2), /* count on the tail (let this N2) */ 
    N is N2 + 1.  /* and N is N2 + 1 */ 

count(X, [Y|T], N) :- 
    X \= Y,   /* if X is not in the head */ 
    count(X, T, N). /* just count the rest */ 
+0

我現在明白了,非常感謝處理自由變量的解釋! – rex 2012-08-12 17:10:24

+0

你不需要步驟'X \ = Y'。只要在前一個謂詞中進行切分,就是當他們*做*相等的時候。 – Ash 2016-03-11 00:41:28

2

您需要使您的子句互斥,第二個子句將在第一個子句中成功。

至於你的錯誤,它是關於信息流。你需要你的第一個子句中交換行,像這樣:

rate(X,[H|T],N):- 
    X == H, 
    rate(X,T,N1), 
    N is N1+1. 

這一變化將使你的斷言是尾遞歸雖然。是尾遞歸,它需要將信息傳遞調用鏈,不接收回來的路上像現在這樣:

rate(X,[H|T],N):- 
    X == H, 
    N1 is N+1, 
    rate(X,T,N1). 

現在你看,你沒有收到最終值這裏,但指定了的初始值。當我們到達的基本情況,我們有我們的結果是:

rate(X, [], N). 

這裏N是結果。如何恢復?使用額外的參數,一個非實例變量,對這個結果進行統一的時候,我們已經到了谷底:

rate(X, [], N, V) :- V is N. 

現在遞歸子句必須適應這種變化,將它傳遞不變下調用鏈。

+0

感謝響應! – rex 2012-08-12 17:15:39

+1

如果您不知道這一點,您有權力立即投票。任何你認爲是好的答案,你都可以得到讚賞。 :) – 2012-08-12 18:26:14

+1

好的,謝謝,新的這種事情。 – rex 2012-08-12 20:54:49

1

如果你喜歡實用的風格,你可以編寫與SWI序言:

:- use_module(library(lambda)). 


rate(X,L,N) :- 
    foldl(\Y^V0^V1^((X = Y->V1 is V0+1; V1 = V0)), L, 0, N).