(Common lisp) Flattening and passing list - lisp

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))))

Related

Insertion Sort in Common lisp

I want to implement the sorting function in common-lisp with this INSERT function
k means cons cell with number & val, and li means list where I want insert k into.
with this function, I can make a list of cell
(defun INSERT (li k) (IF (eq li nil) (cons (cons(car k)(cdr k)) nil)
(IF (eq (cdr li) nil)
(IF (< (car k)(caar li)) (cons (cons(car k)(cdr k)) li)
(cons (car li) (cons (cons(car k)(cdr k)) (cdr li)) )
)
(cond
( (eq (< (caar li) (car k)) (< (car k) (caadr li)) )
(cons (car k) (cons (cons (car k) (cdr k)) (cdr li)) ) )
(t (cons (car li) (INSERT (cdr li) k)) )))))
and what I want is the code of this function below. it has only one parameter li(non sorted list)
(defun Sort_List (li)(...this part...))
without using assignment, and using the INSERT function
Your insert function is very strange. In fact I find it so hard to read that I cn't work out what it's doing except that there's no need to check for both the list being null and its cdr being null. It also conses a lot of things it doesn't need, unless you are required by some part of the specification of the problem to make copies of the conses you are inserting.
Here is a version of it which is much easier to read and which does not copy when it does not need to. Note that this takes its arguments in the other order to yours:
(defun insert (thing into)
(cond ((null into)
(list thing))
((< (car thing) (car (first into)))
(cons thing into))
(t (cons (first into)
(insert thing (rest into))))))
Now, what is the algorithm for insertion sort? Well, essentially it is:
loop over the list to be sorted:
for each element, insert it into the sorted list;
finally return the sorted list.
And we're not allowed to use assignment to do this.
Well, there is a standard trick to do this sort of thing, which is to use a tail-recursive function with an accumulator argument, which accumulates the results. We can either write this function as an explicit auxiliary function, or we can make it a local function. I'm going to do the latter both because there's no reason for a function which is only ever used locally to be globally visible, and because (as I'm assuming this is homework) it makes it harder to submit directly.
So here is this version of the function:
(defun insertion-sort (l)
(labels ((is-loop (tail sorted)
(if (null tail)
sorted
(is-loop (rest tail) (insert (first tail) sorted)))))
(is-loop l '())))
This approach is fairly natural in Scheme, but not very natural in CL. An alternative approach which does not use assignment, at least explicitly, is to use do. Here is a version which uses do:
(defun insertion-sort (l)
(do ((tail l (rest tail))
(sorted '() (insert (first tail) sorted)))
((null tail) sorted)))
There are two notes about this version.
First of all, although it's not explicitly using assignment it pretty clearly implicitly is doing so. I think that's probably cheating.
Secondly it's a bit subtle why it works: what, exactly, is the value of tail in (insert (first tail) sorted), and why?
A version which is clearer, but uses loop which you are probably not meant to know about, is
(defun insertion-sort (l)
(loop for e in l
for sorted = (insert e '()) then (insert e sorted)
finally (return sorted)))
This, however, is also pretty explicitly using assignment.
As Kaz has pointed out below, there is an obvious way (which I should have seen!) of doing this using the CL reduce function. What reduce does, conceptually, is to successively collapse a sequence of elements by calling a function which takes two arguments. So, for instance
(reduce #'+ '(1 2 3 4))
is the same as
(+ (+ (+ 1 2) 3) 4)
This is easier to see if you use cons as the function:
> > (reduce #'cons '(1 2 3 4))
(((1 . 2) . 3) . 4)
> (cons (cons (cons 1 2) 3) 4)
(((1 . 2) . 3) . 4)
Well, of course, insert, as defined above, is really suitable for this: it takes an ordered list and inserts a new pair into it, returning a new ordered list. There are two problems:
my insert takes its arguments in the wrong order (this is possibly why the original one took the arguments in the other order!);
there needs to be a way of 'seeding' the initial sorted list, which will be ().
Well we can fix the wrong-argument-order either by rewriting insert, or just by wrapping it in a function which swaps the arguments: I'll do the latter because I don't want to revisit what I wrote above and I don't want two versions of the function.
You can 'seed' the initial null value by either just prepending it to the list of things to sort, or in fact reduce has a special option to provide the initial value, so we'll use that.
So using reduce we get this version of insertion-sort:
(defun insertion-sort (l)
(reduce (lambda (a e)
(insert e a))
l :initial-value '()))
And we can test this:
> (insertion-sort '((1 . a) (-100 . 2) (64.2 . "x") (-2 . y)))
((-100 . 2) (-2 . y) (1 . a) (64.2 . "x"))
and it works fine.
So the final question the is: are we yet again cheating by using some function whose definition obviously must involve assignment? Well, no, we're not, because you can quite easily write a simplified reduce and see that it does not need to use assignment. This version is much simpler than CL's reduce, and in particular it explicitly requires the initial-value argument:
(defun reduce/simple (f list accum)
(if (null list)
accum
(reduce/simple f (rest list) (funcall f accum (first list)))))
(Again, this is not very natural CL code since it relies on tail-call elimination to handle large lists, but it makes the point that you can do this without assignment.)
And so now we can write one final version of insertion-sort:
(defun insertion-sort (l)
(reduce/simple (lambda (a e)
(insert e a))
l '()))
And it's easy to check that this works as well.

LISP FUNCTION - Return the count of numbers of the list that are bigger of the first element

I want to solve a lisp function that returns a NUMBER(count) of numbers which are greater than the first number in the list.The list is a linear list of numbers.
(defun foo (lst)
(cond ((null lst) 0)
(car = k)
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
My problem is that I cannot keep the first element and compare it with the others.
Let's take apart your problem:
You have a set of numbers. Really, you have a “special” first number, and then the rest of them. Specifically, you probably want only real numbers, because “less than” does not make sense in terms of complex (imaginary) numbers.
You can use first to get the first number from the list, and rest for the others.
Of these, you want to count any that are not greater than the first.
So let's start with sort of pseudocode
(defun count-numbers-greater-than-first (list)
;; split out first and rest
;; call the real count function
)
Well, we know now that we can use first and rest (also, as you used, historically car and cdr), so:
(defun count-numbers-greater-than-first (list)
(count-numbers-greater-than (first list) (rest list))
You already probably know that > is used to test whether real numbers are greater than one another.
A quick look at the CLHS reveals a nice function called count-if
(defun count-numbers-not-greater-than (reference other-numbers)
(count-if ??? other-numbers))
The ??? needs to be an object of function type, or the name of a function. We need to “curry” the reference (first number) into that function. This means we want to create a new function, that is only used for one run through the count-if, that already has “closed over” the value of reference.
If we knew that number would always be, say, 100, that function would look like this:
(defun greater-than-100 (number)
(> number 100))
That function could then get used in the count-if:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (function greater-than-100)
other-numbers))
(defun count-numbers-greater-than (reference other-numbers)
(count-if #'greater-than-100 other-numbers))
But that doesn't solve the problem of getting the reference number “curried” into the function.
Without reaching for Alexandria (I'll explain in a moment), you can use a lambda form to create a new, anonymous function right here. Since reference is available within count-numbers-not-greater-than, you can use its value within that lambda. Let's convert for 100 first:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number 100))
other-numbers))
Now we can use reference:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number reference))
other-numbers))
And, in fact, you could even merge this back into the other function, if you wanted:
(defun count-numbers-greater-than-first (list)
(count-if (lambda (number) (> number (first list)))
(rest list)))
That Alexandria thing
But, what about Alexandria? Alexandria is a collection of super-useful utility functions that's available in Quicklisp or elsewhere.
(ql:quickload "alexandria")
(use-package #:alexandria)
Of course, you'd normally use it in your own defpackage
(defpackage my-cool-program
(:use :common-lisp :alexandria))
Two of the things it provides are curry and rcurry functions. It turns out, that lambda function in there is a really common case. You have an existing function — here, > — that you want to call with the same value over and over, and also some unknown value that you want to pass in each time.
These end up looking a lot like this:
(lambda (x) (foo known x))
You can use curry to write the same thing more concisely:
(curry #'foo known)
It also work with any number of arguments. RCurry does the same, but it puts the unknown values “x” at the left, and your known values at the right.
(lambda (x) (foo x known)) = (rcurry #'foo known)
So another way to write the count-if is:
(defun count-numbers-greater-than-first (list)
(count-if (rcurry #'> (first list))
(rest list)))
* (count-numbers-greater-than-first '(10 9 8 7 11 12))
2
Your function indented correctly looks like this:
(defun foo (lst)
(cond ((null lst) 0)
(car = k) ; strange cond term
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
I have commented the second term in your cond. It is quite strange. It first evaluates the variable car (not the function #'car). If car is not nil it first evaluates the variable = (not the function #'=) and since it is not the last consequent expression in the cond term it throws that away and returns the last which is k.
Secondly you write that you say you use the first element as comparison, however you call it k in your function but it is not defined anywhere. You need to do something before you do the recursion and thus you cannot let the actual function do the recursion since it will take the first element each time. Here is where labels can be used:
;; didn't call it foo since it's not very descriptive
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list)
(cond ((null list) 0)
((> (car list) first)
(1+ (helper (cdr list))))
(t (helper (cdr list))))))
(helper (cdr list)))))
Of course. Since you now have the possibility to add more arguments I would have added an accumulator:
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list acc)
(cond ((null list) acc)
((> (car list) first)
(helper (cdr list) (1+ acc)))
(t (helper (cdr list) acc)))))
(helper (cdr list) 0))))
And of course recursion might blow the stack so you should really write it without in Common Lisp:
(defun count-larger-than-first (list)
(let ((first (car list)))
(loop :for element :in (cdr list)
:counting (> element first))))
There are higher order functions that count too which might be more suitable:
(defun count-larger-than-first (list)
(let ((first (car list)))
(count-if (lambda (element) (> element first))
(cdr list))))

Checking circularity in lisp - same variable through recursive function

I'm trying to create a function that would test whether the given list is circular with a re-starting point being the beginning of the list.
Expected results:
(setq liste '(a b c))
(rplacd (cddr liste) liste)
(circular liste) => t
(circular '(a b c a b c)) => nil
As I simply want to test if any subsequent item is 'eq' to the first one, I don't want to build the whole tortoise and hare algorithm.
Here is my code :
(defun circular (liste)
(let (beginningliste (car liste)))
(labels ( (circ2 (liste)
(cond
((atom liste) nil)
((eq (car liste) beginningliste) t)
(t (circ2 (cdr liste)))
) ) ) ) )
It doesn't give the expected result but I don't understand where my error is
I'm not sure I'm using 'labels' correctly
Is there a way to do that without using 'labels'?
Edit. I guess I have answered my third question as I think I have found a simpler way. Would this work?
(defun circular (liste)
(cond
((atom liste) nil)
((eq (car liste) (cadr liste)) t)
(t (circular (rplacd liste (cddr liste))))
)
)
First, the behavior is undefined when you mutate constant data: when you quote something (here the list), the Lisp environment has the right to treat it as a constant. See also this question for why defparameter or defvar is preferred over setq. And so...
(setq list '(a b c))
(rplacd (cddr list) list)
... would be better written as:
(defparameter *list* (copy-list '(a b c)))
(setf (cdr (last *list*)) *list*)
Second, your code is badly formatted and has bad naming conventions (please use dashes to separate words); here it is with a conventional layout, with the help of emacs:
(defun circularp (list)
(let (first (car list)))
(labels ((circ2 (list)
(cond
((atom list) nil)
((eq (car list) first) t)
(t (circ2 (cdr list))))))))
With that formatting, two things should be apparent:
The let contains no body forms: you define local variables and never use them; you could as well delete the let line.
Furthermore, the let is missing one pair of parenthesis: what you wrote defines a variable name first and another one named car, bound to list. I presume you want to define first as (car list).
You define a local circ2 function but never use it. I would expect the circularp function (the -p is for "predicate", like numberp, stringp) to call (circ2 (cdr list)). I prefer renaming circ2 as visit (or recurse), because it means something.
With the above corrections, that would be:
(defun circularp (list)
(let ((first (car list)))
(labels ((visit (list)
(cond
((atom list) nil)
((eq (car list) first) t)
(t (visit (cdr list))))))
(visit (cdr list)))))
However, if your list is not circular but contains the same element multiple times (like '(a a b)), you will report it as circular, because you inspect the data it holds instead of the structure only. Don't look into the CAR here:
(defun circularp (list)
(let ((first list))
(labels ((visit (list)
(cond
((atom list) nil)
((eq list first) t)
(t (visit (cdr list))))))
(visit (cdr list)))))
Also, the inner function is tail recursive but there is no guarantee that a Common Lisp implementation automatically eliminates tail calls (you should check with your implementation; most can do it on request). That means you risk allocating as many call stack frames as you have elements in the list, which is bad. Better use a loop directly:
(defun circularp (list)
(loop
for cursor on (cdr list)
while (consp cursor)
thereis (eq cursor list)))
Last, but not least: your approach is a very common one but fails when the list is not one big circular chain of cells, but merely contains a loop somewhere. Consider for example:
CL-USER> *list*
#1=(A B C . #1#)
CL-USER> (push 10 *list*)
(10 . #1=(A B C . #1#))
CL-USER> (push 20 *list*)
(20 10 . #1=(A B C . #1#))
(see that answer where I explain what #1= and #1# mean)
The lists with numbers in front exhibit circularity but you can't just use the first cons cell as a marker, because you will be looping forever inside the sublist that is circular. This is the kind or problems the Tortoise and Hare algorithm solves (there might be other techniques, the most common being storing visited elements in a hash table).
After your last edit, here is what I would do if I wanted to check for circularity, in a recursive fashion, without labels:
(defun circularp (list &optional seen)
(and (consp list)
(or (if (member list seen) t nil)
(circularp (cdr list) (cons list seen)))))
We keep track of all the visited cons cells in seen, which is optional and initialized to NIL (you could pass another value, but that can be seen as a feature).
Then, we say that a list is circular with respect to seen if it is a cons cell which either: (i) already exists in seen, or (ii) is such that its CDR is circular with respect to (cons list seen).
The only additional trick here is to ensure the result is a boolean, and not the return value of member (which is the sublist where the element being searched for is the first element): if your environment has *PRINT-CIRCLE* set to NIL and the list is actually circular, you don't want it to try printing the result.
Instead of (if (member list seen) t nil), you could also use:
(when (member list seen))
(position list seen)
and of course (not (not (member list seen)))

Lisp function: union

I have a lisp homework I am having a hard time with it.
I have to write a function that perform a union operation. The function takes 2 inputs, either in the form of either atom or list and unions every element, preserving the order and stripping off all levels of parenthesis.
The output for the function:
(my-union 'a 'b) ;; (a b)
(my-union 'a '(b)) ;; (a b)
(my-union '(a b) '(b c)) ;; (a b c)
(my-union '(((a))) '(b(c((d e))a))) ;; (a b c d e)
I am fairly new to lisp.
Here is what I have written so far and it works only for the third example:
(defun new-union (a b)
(if (not b)
a
(if (member (car b) a)
(new-union a (cdr b))
(new-union (append a (list (car b))) (cdr b)))))
Any help would be appreciated!
Since this is your first homework, and you are new to Lisp, here is a very simple top-down approach, not worrying about performance, and making good use of the tools CL offers:
In Common Lisp, there is already a function which removes duplicates: remove-duplicates. Using it with the :from-end keyword-argument will "preserve order". Now, imagine you had a function flatten, which flattens arbitrarily nested lists. Then the solution to your question would be:
(defun new-union (list1 list2)
(remove-duplicates (flatten (list list1 list2)) :from-end t))
This is how I would approach the problem when no further restrictions are given, and there is no real reason to worry much about performance. Use as much of the present toolbox as possible and do not reinvent wheels unless necessary.
If you approach the problem like this, it boils down to writing the flatten function, which I will leave as an exercise for you. It is not too hard, one easy option is to write a recursive function, approaching the problem like this:
If the first element of the list to be flattened is itself a list, append the flattened first element to the flattened rest. If the first element is not a list, just prepend it to the flattened rest of the list. If the input is not a list at all, just return it.
That should be a nice exercise for you, and can be done in just a few lines of code.
(If you want to be very correct, use a helper function to do the work and check in the wrapping function whether the argument really is a list. Otherwise, flatten will work on atoms, too, which may or may not be a problem for you.)
Now, assuming you have written flatten:
> (defun new-union (list1 list2)
(remove-duplicates (flatten (list list1 list2)) :from-end t))
NEW-UNION
> (new-union 'a 'b)
(A B)
> (new-union 'a '(b))
(A B)
> (new-union '(a b) '(b c))
(A B C)
> (new-union '(((a))) '(b (c ((d e)) a)))
(A B C D E)
One way to approach this is to separate your concerns. One is flattening; another is duplicates-removing; yet another is result-building.
Starting with empty list as your result, proceed to add into it the elements of the first list, skipping such elements that are already in the result.
Then do the same with the second list's elements, adding them to the same result list.
(defun my-union (a b &aux (res (list 1)) (p res))
(nadd-elts p a)
(nadd-elts p b)
(cdr res))
nadd-elts would add to the end of list, destructively updating its last cell (pointed to by p) using e.g. rplacd. An example is here.
To add elements, nadd-elts would emulate the flattening procedure, and add each leaf element into p after checking res for duplicates.
Working in functional style, without destructive update, the general approach stays the same: start with empty result list, add first list into it - without duplicates - then second.
(defun my-union (a b &aux res)
(setq res (add-into res a))
(setq res (add-into res b))
res)
Now we're left with implementing the add-into function.
(defun add-into (res a &aux r1 r2)
(cond
((atom a) .... )
(T (setq r1 (add-into res (car a)))
(setq r2 (............ (cdr a)))
r2)))
The above can be re-written without the auxiliary variables and without set primitives. Try to find out how... OK here's what I meant by that:
(defun my-union (a b) (add-into NIL (cons a b)))
(defun add-into (res a)
(cond
((atom a) .... )
(T (add-into (add-into res (car a))
(cdr a)))))
Unless you are not allowed to use hash table (for some reason I've encountered this as a requirement before), you could come up with an ordering function that will help you build the resulting set in the way, that you don't have to repeat the search over and over again.
Also, since nested lists are allowed your problem scales down to only removing duplicates in a tree (as you can simply append as many lists as you want before you start processing them.
Now, I'll try to show few examples of how you could do it:
;; Large difference between best and worst case.
;; Lists containing all the same items will be processed
;; in square time
(defun union-naive (list &rest lists)
(when lists (setf list (append list lists)))
(let (result)
(labels ((%union-naive (tree)
(if (consp tree)
(progn
(%union-naive (car tree))
(when (cdr tree) (%union-naive (cdr tree))))
(unless (member tree result)
(setq result (cons tree result))))))
(%union-naive list) result)))
;; Perhaps the best solution, it is practically linear time
(defun union-hash (list &rest lists)
(when lists (setf list (append list lists)))
(let ((hash (make-hash-table)) result)
(labels ((%union-hash (tree)
(if (consp tree)
(progn
(%union-hash (car tree))
(when (cdr tree) (%union-hash (cdr tree))))
(setf (gethash tree hash) t))))
(%union-hash list))
(maphash
#'(lambda (a b)
(declare (ignore b))
(push a result)) hash)
result))
;; This will do the job in more time, then the
;; solution with the hash-map, but it requires
;; significantly less memory. Memory is, in fact
;; a more precious resource some times, but you
;; have to decide what algo to use based on the
;; data size
(defun union-flatten (list &rest lists)
(when lists (setf list (append list lists)))
(labels ((%flatten (tree)
(if (consp tree)
(if (cdr tree)
(nconc (%flatten (car tree))
(%flatten (cdr tree)))
(%flatten (car tree)))
(list tree))))
;; the code below is trying to do something
;; that you could've done using
;; (remove-duplicates (%flatten list))
;; however sorting and then removing duplicates
;; may prove to be more efficient
(reduce
#'(lambda (a b)
(cond
((atom a) (list a))
((eql (car a) b) b)
(t (cons b a))))
(sort (%flatten list)
#'(lambda (a b)
(string< (symbol-name a)
(symbol-name b)))))))
(union-naive '(((a))) '(b(c((d e))a)))
(union-hash '(((a))) '(b(c((d e))a)))
(union-flatten '(((a))) '(b(c((d e))a)))
Notice that the function I've used to order elements is not universal, but you would probably be able to come up with an alternative function for any sort of data. Any fast hashing function in general would do, I've used this one for simplicity.

Calling functions by name at runtime

I realize that a function can be referenced using #'PRINT to reference the PRINT function. If we have a list S where the first element is 'PRINT , can we reference this using #(car S) ?
Say I'm looking at a list where the elements in the list are atoms which are the names of some functions. Currently, I can do this:
(defun aritheval (S)
(funcall
(cond
((eq '+ (car S)) #'+)
((eq '- (car S)) #'-)
((eq '* (car S)) #'*)
((eq '/ (car S)) #'/)
)
'2
'3
)
)
This function would compute 2+3, 2-3, 2*3 or 2/3 depending on the first element in list S. S contains the names of these functions.
#(car S) makes no sense. The syntax exists but means a vector with symbols CAR and S.
use
(funcall (first somelist) someargument)
or
(apply (first somelist) a-list-of-arguments)
Your function is non-Lispy formatted.
Trailing parentheses are not used in proper Lisp code. You also don't need to quote numbers. Numbers are self-evaluating, they evaluate to themselves. Also we now may prefer FIRST over CAR and REST over CDR. The functions do the same, but the names are better. Whenever we deal with simple lists, FIRST, SECOND, THIRD, ... and REST are used.
(defun aritheval (S)
(funcall (cond ((eq '+ (car S)) #'+)
((eq '- (car S)) #'-)
((eq '* (car S)) #'*)
((eq '/ (car S)) #'/))
2 3)))
Since symbols can be used as names for global functions, above is not necessary.
This function below does the same, given the mapping from symbol to function is the same.
(defun aritheval (s)
(funcall (first s) 2 3)))