2017-02-18 34 views
1

的原子數目我不明白以下內容:在樹上

(COUNT原子「(A(B)C))應該返回五位。

樹中的A,B和C以及兩個NIL。

寫一個函數COUNT-ATOMS返回樹中的原子數。

我嘗試這樣做:

(defun count-atoms(l) 
    (cond 
    ((null l) 0) 
    (t (+ (cond 
      ((atom (car l)) 1) 
      (t 0)) 
      (count-atoms (cdr l)))))) 

然而,(COUNT-ATOMS '(A (B) C))回報2.

應該怎麼辦返回5呢?

您能否解釋更多細節?

回答

4

如果你想建立(a (b) c)在運行時,僅使用consquote,你可以這樣寫:

(cons 'a      
     (cons (cons 'b nil)  
      (cons 'c nil))) 

有5個原子(A,B,C和兩個零)樹正在興建。在實踐中,您可以使用更簡單的符號,如(list 'a (list 'b) 'c)

在你的函數中,你不會遞歸到你的樹的CARS中,只是CDRS。此外,當CAR不是原子時,例如當您遇到(B)時,您將添加零(第二個cond中的默認子句)(編輯。如kmkaplan所述,您也可以計數零,無第一個cond)

一個簡單的方案是這樣的,基於typecase

(defun count-atoms (form) 
    (typecase form 
    (atom 1) 
    (cons (+ (count-atoms (car form)) 
      (count-atoms (cdr form)))))) 
  • 當遇到一個原子,則結果爲1
  • 當你有一個cons單元,你總結原子數在它的車和司機。

typecase根據其參數的類型進行調度,此處爲form。每個子句的語法如下:(type ...body...),其中type是一個類型的名稱,...body...一個或多個表達式(隱含的progn):如果參數匹配type,則最後一個值是typecase的返回值。

第一項從句(atom 1)說:如果表格是原子,返回1。下面一個,(cons ...)說:否則,如果表格是一個cons單元,...。這裏,atom是一個類型的名稱,它代表不是cons的所有內容。當然,一旦你知道某物不是原子,你就知道它必然是cons,而第二個測試是多餘的。但是,它更具可讀性,任何體面的編譯器都會優化第二個測試。

還有一個名爲atom的函數,它是測試值是否是原子的謂詞。這就是爲什麼,當你寫上自己的(atom 1),在REPL,它返回T.

又見wikipedia和賽貝爾的實用的Common Lispchapter about lists

+0

回答謝謝。 但我有一個問題。 (原子1)在這裏意味着什麼? (Atom 1)從T出來,但是它如何像第一個一樣起作用? –

+0

@임민섭查看有關原子的編輯。 – coredump

2

你的函數有兩個問題。第一個在coredump's answer中整齊地描述,你的COUNT-ATOMS只在尾部遞歸(CDR),並忘記在你的反應細胞的CAR元素上遞歸(L)。因此它不能計算B原子。

第二個問題是,您將NIL計爲0,而它是原子,應計爲1