2016-05-01 40 views
0

我在這裏要做的是首先弄平任何給定的列表,然後將該列表傳遞給我的加密函數。雖然這不起作用,我不知道爲什麼。 這裏是我到目前爲止,(通常lisp)展平和通過名單

(defun flatten (l) 
    (cond ((null l) l) 
     ((atom l) (list l)) 
     (t (loop for a in l appending (flatten a)))) 

) 



(defun encrypt(enctext) 
(flatten enctext) 

    (if(eq 'A (first enctext)) ;If the first charcater equals 'A'... 
     (progn     ;To allow multiple statements in an if statement 
     (prinC#\B)    ; First statement, print this character 
     (encrypt(rest enctext)))) ;Second statement, run function again passing the rest of the characters 

    (if(eq 'B (first enctext)) 
     (progn 
     (prinC#\C) 
     (encrypt(rest enctext)))) 


) 

這是如何我調用加密功能

(encrypt '((A)(B)) 

我應該叫我「加密」功能的「扁平化」的功能?或者在遞歸調用之後在「扁平化」函數中調用「加密」? 我該如何正確地通過展平名單?

回答

1

FLATTEN不破壞性地修改列表。它會創建一個包含展平內容的新列表。你必須使用它的返回值而不是原來的ENCTEXT。這是很容易通過調用ENCRYPT實現,如:

(encrypt (flatten '((A) (B)))) 

和刪除ENCRYPTFLATTEN呼叫。這是你的代碼的有些清潔版本:

(defun encrypt (enctext) 
    (unless (endp enctext) 
    (princ (ecase (first enctext) ; I'm assuming the input shouldn't 
      (A #\B)    ; contain any symbols that aren't 
      (B #\C)))   ; handled here. Otherwise use CASE 
    (encrypt (rest enctext)))) ; instead of ECASE. 

如果你想這樣做,沒有一個單獨的函數調用拼合列表中,你需要遞歸下降到裏面ENCRYPT輸入列表中。喜歡的東西:

(defun encrypt (enctext) 
    (unless (endp enctext) 
    (let ((first (first enctext))) 
     (if (atom first) 
      (princ (ecase first 
        (A #\B) 
        (B #\C))) 
      (encrypt first))) 
    (encrypt (rest enctext)))) 

(encrypt '((A) (B))) 
; BC 

當然,如果你沒有理由要做到這一點使用遞歸的深度和廣度,循環會使代碼更加清晰:

(defun encrypt (enctext) 
    (dolist (el enctext) 
    (if (atom el) 
     (princ (ecase el 
       (A #\B) 
       (B #\C))) 
     (encrypt el)))) 
+0

謝謝!我試圖將一切都納入一個功能,但我甚至不知道你是否可以做到這一點。 – Jcan1995

+0

@JoshuaCantero我添加了另一個例子,它不會變扁。 – jkiiski

+0

是的,我注意到,它有很大的幫助。 – Jcan1995