What I'm trying to do here is first flatten any given list and then pass that list into my encrypt function. Although this is not working and I'm not sure why. Here is what I have so far,
(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))))
)
And this is how i'm calling the encrypt function
(encrypt '((A)(B))
Should I call the "flatten" function within my "encrypt" function? Or call "encrypt" within the "flatten" function after the recursive calls? And how would I properly pass the flattened list?
FLATTEN
doesn't destructively modify the list. It creates a new list with the flattened contents. You have to use its return value instead of the original ENCTEXT
. That is easily achieved by calling ENCRYPT
like:
(encrypt (flatten '((A) (B))))
And removing the call to FLATTEN
from ENCRYPT
. Here's a somewhat cleaner version of your code:
(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.
If you want to do this without a separate function call to flatten the list, you'll need to recursively descend into the input list inside ENCRYPT
. Something like:
(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
Of course if you don't have a reason to want to do this using recursion for both depth and breadth, a loop would make the code much clearer:
(defun encrypt (enctext)
(dolist (el enctext)
(if (atom el)
(princ (ecase el
(A #\B)
(B #\C)))
(encrypt el))))