constuct mixed list - list

Hi everyone I am trying to construct a mixed list with letters and numbers. For example when you call the funciton (inc-list1 '(cat 4 dog 3 x 5)) => (cat 5 dog 4 x 6). I am pretty sure the logic is right, so i think i am missing something from the syntax. Here is my code
(defun inc-list1 (list)
(cond ((null list)
nil
)
(numberp (first list)
(cons ( + 1 (first list)) (inc-list1 (rest list)))
)
(T
cons (first list) (inc-list1 (rest list))
)
)
)

An example of how you could have approached the problem:
(defun mapcar-if (list test if-true &optional (otherwise #'identity))
(mapcar
#'(lambda (x)
(funcall
(if (funcall test x)
if-true
otherwise) x)) list))
(mapcar-if '(cat 4 dog 3 x 5) #'numberp #'1+)
Which would make the function a little bit more useful in other situations too.
Your code:
(T cons ...) doesn't do what you think it does. You probably wanted to call cons rather then simply mention it. Mentioning it in the way you did has no effect and no side effect (it would have side effect, if the symbol cons was unbound - i.e. you'd receive an error). Whatever happens next is the result of the previous error. Calling (first list) has no side effect too (in your case).
"Consing" the list in the way you did isn't a particularly good technique. Because this technique is already implemented in other functions (like mapcar, reduce etc.) They were written with the purpose in mind to reduce the amount of text you have to type to write a program, and to make it easier to read, once you have written it. ;)

There are various typos in your code. Here is a fixed version
(defun inc-list1 (list)
(cond ((null list)
nil
)
((numberp (first list))
(cons ( + 1 (first list)) (inc-list1 (rest list)))
)
(t
(cons (first list) (inc-list1 (rest list)))
)
)
)
Note the added parens around the numberp and cons function calls and the t in lower case.

Related

How to transform a list into a set in LISP?

I have been trying to transform a linear list into a set but with no avail. Everytime I run this, I get some weird compilation errors like "badly formed lambda" which points to the way I use append. Here is my code:
(defun mem(e l)
(cond
((null l) nil)
((equal e (car l)) t)
((listp (car l)) (mem e (car l)))
(t(mem e (cdr l)))
)
)
(defun st(l k)
(cond
((null l) nil)
(( mem '(car l) 'k) (st (cdr l) k))
((listp (car l)) (st (car l) k))
( t (st (cdr l) (append((car l) k)) ))
(t(mem e (cdr l)))
)
)
EDIT: frankly I just want to remove the duplicates from list l
Prefer Standard Library Functions
EDIT: frankly I just want to remove the duplicates from list l
Common Lisp has a remove-duplicates function. The documentation inclues examples:
Examples:
(remove-duplicates "aBcDAbCd" :test #'char-equal :from-end t) => "aBcD"
(remove-duplicates '(a b c b d d e)) => (A C B D E)
(remove-duplicates '(a b c b d d e) :from-end t) => (A B C D E)
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr) => ((BAR #\%) (BAZ #\A))
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr :from-end t) => ((FOO #\a) (BAR #\%))
Are you trying to flatten the list too?
From your code for mem, where you do:
((listp (car l)) (mem e (car l)))
it looks like you want your member function to also recurse into sublists. That's a bit questionable, even when working with sets, since sets can traditionally include other sets. E.g., {{3},{4},5} is a set containing 5, the set {3}, and the set {4}. It's not the same as the set {3,4,5}. Your st function also looks like it's trying to recurse into lists, which makes it seem like you want to flatten you lists, too. Again, that's a bit questionable, but if you want to do that, then your conversion to a set would be easier as a "flatten, then remove duplicates" process:
(defun flatten (list)
"Returns a fresh list containing the leaf elements of LIST."
(if (listp list)
(mapcan 'flatten list)
(list list)))
;; CL-USER> (flatten '(1 2 (3 4) 5 ((6))))
;; (1 2 3 4 5 6)
(defun to-set (list)
"Returns a set based on the elements of LIST. The result
is a flat list containing the leaf elements of LIST, but
with any duplicate elements removed."
(delete-duplicates (flatten list)))
;; CL-USER> (to-set '(1 3 (3 4) ((4) 5)))
;; (1 3 4 5)
Notes
I get some weird compilation errors like "badly formed lambda" which points to the way I use append.
Yes, you're trying to call append like: (append((car l) k)). That's actually not a problem for append. Remember, the syntax for a function call in Lisp is (function argument…). That means that you've got:
(append ((car l) k))
<function> <argument1>
But your argument1 is also a function call:
((car l) k )
<function> <argument1>
In Common Lisp, you can't use (car l) as a function. The only thing that can appear for a function is a symbol (e.g., car, append) or a lambda expression (e.g., (lambda (x) (+ x 1)).
You want to call (append (car l) k) instead.
First, CL does not have a set data type.
Lists, however, can be used as sets, you do not need to write any special code for that.
Second, I don't understand what your st function is supposed to do, but I bet that in the second cond clause you should not quote (car l) and k. You should use meaningful names for your functions and avoid abbreviations. As per your explanation in the comment, you should use pushnew instead.
Third, your mem function is quite weird, I am pretty sure you do not mean what you wrote: e is searched along a path in the tree l, not in the list l. As per your explanation in the comment, you should check both car and cdr:
(defun tree-member (tree element &key (test #'eql))
(if (consp tree)
(or (tree-member (car tree) element :test test)
(tree-member (cdr tree) element :test test))
(funcall test element tree)))

How can I recursively check if a list is sorted in Lisp?

I want to write a recursive function that checks the list and either returns true if the list is in ascending order or NIL otherwise. If the list is empty it is still true. I am completely new to Lisp, so its still very confusing.
(defun sorted (x)
(if (null x)
T
(if (<= car x (car (cdr x)))
(sorted (cdr x))
nil)))
The recursive version:
(defun sorted (list)
(or (endp list)
(endp (cdr list))
(and (<= (first list) (second list))
(sorted (cdr list)))))
The more idiomatic loop-based predicate accepting a :test argument:
(defun sortedp (list &key (test #'<=))
(loop for (a b) on list
while b
always (funcall test a b)))
The version accepting a :key; we only call the key function once per visited element:
(defun sortedp (list &key (test #'<=) (key #'identity))
(loop for x in list
for old = nil then new
for new = (funcall key x)
for holdp = T then (funcall test old new)
always holdp))
Some tests:
(loop for k in '(()
((1))
((1) (2))
((2) (1))
((1) (2) (3))
((3) (2) (1)))
collect (sortedp k :test #'> :key #'car))
=> (T T NIL T NIL T)
This one also works with other kinds of sequences:
(defun sortedp (sequence &key (test #'<=) (key #'identity))
(reduce (lambda (old x &aux (new (funcall key x)))
(if (or (eq old t)
(funcall test old new))
new
(return-from sortedp nil)))
sequence
:initial-value t))
The above test gives:
(T 1 NIL 1 NIL 1)
... which is a correct result thanks to generalized booleans.
If you are doing your homework (seems so), then the above answers are fine. If you are just learning Lisp, and don't have constraints about recursivity, then the following might give you a glimpse about the power of Lisp:
(defun sorted (l)
(or (null l) (apply #'< l)))
The first problem with your solution is the base case You need to stop not at the end of the list, but when looking at the last to elements, as you need to elements to do the comparison. Also the parens are missing in the call to (car x)
(defun sorted (list)
(if (endp (cddr list))
(<= (car list) (cadr list))
(and (<= (car list) (cadr list))
(sorted (cdr list)))))
Bare in mind that recursive solutions are discouraged in CL

LISP - get last list of a list

I'm trying to figure out how to obtain the last (non-empty) list from within another list, or return nil if there is no such list (recursively). This is an homework assignment, and as such I am looking for help on the method, not necessarily the code for it. Example:
(lastele '(1 (2 3) 4 5)) ;=> (2 3)
(lastele '(1 (2 3) (4 5)) ;=> (4 5)
(lastele '(1 2 3 4 5)) ;=> NIL
I was trying to run through the list, and if I encountered a sublist, I would check to see if the rest of the list contained any more non-empty sublists, if it did, continue with setting the list to that, and repeating until we had a null list.
(defun lastele2 (L)
(if (null L)
'()
(if (hasMoreLists (rest L))
(lastele2 (rest L))
(first L))))
It seems as if I can't get hasMoreLists to work, though. Returning t or f within is just erroring. Is this the best way to go about this?
First of all, note that you're implicitly assuming that none of the sublists are the empty list; if they could be the empty list, then nil is an ambiguous result, because you can't tell whether your function returned nil because there were no sublists, or because there were, and the last one was empty. E.g.,
(fn '(1 2 3 4 5)) ;=> nil because there are no sublists
(fn '(1 2 3 () 5)) ;=> nil because there are sublists, and the last one is nil
So, under the assumption that there are no non-null sublists in the toplevel list, we can continue.
A non-homework solution using standard functions
You don't need to write this. You can just use find-if with the predicate listp and specify that you want to search from the end by using the keyword argument :from-end t:
CL-USER> (find-if 'listp '(1 (2 3) 4 5) :from-end t)
(2 3)
CL-USER> (find-if 'listp '(1 (2 3) (4 5)) :from-end t)
(4 5)
CL-USER> (find-if 'listp '(1 2 3 4 5) :from-end t)
NIL
Writing your own
If you need to write something like this, your best bet is to use a recursive function that searches a list and keeps track of the most recent list element that you've seen as the result (the starting value would be nil) and when you finally reach the end of the list, you'd return that result. E.g.,
(defun last-list (list)
(labels ((ll (list result) ; ll takes a list and a "current result"
(if (endp list) ; if list is empty
result ; then return the result
(ll (cdr list) ; else continue on the rest of list
(if (listp (car list)) ; but with a "current result" that is
(car list) ; (car list) [if it's a list]
result))))) ; and the same result if it's not
(ll list nil))) ; start with list and nil
The local function ll here is tail recursive, and some implementations will optimize it into a loop, but would be more idiomatic to use a genuine looping construct. E.g., with do, you'd write:
(defun last-list (list)
(do ((result nil (if (listp (car list)) (car list) result))
(list list (cdr list)))
((endp list) result)))
If you don't want to use labels, you can define this as two functions:
(defun ll (list result)
(if (endp list)
result
(ll (cdr list)
(if (listp (car list))
(car list)
result))))
(defun last-list (list)
(ll list nil))
Alternatively, you could make last-list and ll be the same functions by having last-list take the result as an optional parameter:
(defun last-list (list &optional result)
(if (endp list)
result
(last-list (cdr list)
(if (listp (car list))
(car list)
result))))
In all of these cases, the algorithm that you're implementing is essentially iterative. It's
Input: list
result ← nil
while ( list is not empty )
  if ( first element of list is a list )
    result ← first element of list
  end if
  list ← rest of list
end while
return result
Something based on the code in the question
We can still find something that's a bit closer to your original approach (which will use more stack space), though. First, your original code with proper indentation (and some newlines, but there's more flexible in coding styles there):
(defun lastele2 (L)
(if (null L)
'()
(if (hasMoreLists (rest L))
(lastele2 (rest L))
(first L))))
The approach it looks like you're trying to use is to define the last sublist of a list L as:
nil, if L is empty;
if (rest L) has some sublists, whatever the last sublist of (rest L) is; and
if (rest L) doesn't have some sublists, then (first L).
That last line isn't quite right, though. It needs to be
if (rest L) doesn't have some sublists, then (first L) if (first L) is a list, and nil otherwise.
Now, you've already got a way to check whether (rest L) has any (non-null) sublists; you just check whether (lastele2 (rest L)) returns you nil or not. If it returns nil, then it didn't contain any (non-null) sublists. Otherwise it returned one of the lists. This means that you can write:
(defun last-list (list)
(if (endp list) ; if list is empty
nil ; then return nil
(let ((result (last-list (rest list)))) ; otherwise, see what (last-list (rest list)) returns
(if (not (null result)) ; if it's not null, then there were more sublists, and
result ; last-list returned the result that you wantso return it
(if (listp (first list)) ; otherwise, if (first list) is a list
(first list) ; return it
nil))))) ; otherwise return nil
This is implementing the an essentially recursive algorithm; the value of the subproblem is returned, and then lastList returns a value after examining it that result:
Function: lastList(list)
if ( list is empty )
   return nil
else
   result ← lastList(list)
  if ( result is not nil )
     return result
  else if ( first element of list is a list )
     return first element of list
  else
     return nil
  end if
end if
No, it's not the best way to go about this. To find whether the rest of list has more lists, you need to search it - and if it has, you restart scanning over the rest of your list.
I.e. you do a lot of back and forth.
Instead, just search along, and update a side variable to point to any list you find along the way.
(defun lastele (lst &aux a) ; a is NIL initially
(dolist (e lst a) ; return a in the end
(if (consp e) (setq a e))))

LISP Need some helps to solve one exsercise with LIST

This is what I must do! I have a lot of list and I must return list without integer.
(functInt '(f 3 (v) (((7))) n ()))
-------->
(f (v) ((())) n ())
This is my code:
(defun functInt (list)
(cond ((atom list) (if (not(integerp list)) list))
((null (cdr list)) (functInt (car list)))
(T (cons (functInt (car list)) (functInt (cdr list))))))
But what I get is (F NIL V NIL N)
How can I correct my code to get the output that I want?
One of the problems is that
(if (not (integerp list)) list)
returns nil when list is an integer, so you're replacing integers with nil.
I think the only way to get this right is by assuming that no-one will ever call your function on a non-list value. Then you can rewrite it in the form
(defun functInt (x)
(cond ((atom x) x)
((integerp (car x)) FOO)
(t BAR)))
where I leave the expressions to substitute for FOO and BAR as exercises. (functInt 3) will still return 3, but that violates the function's contract.
Note that (atom nil) is true, so you don't need a special case for (null x).
It might be helpful to not try to do all this in a single function, but use a higher-order function to solve the general case and then only fill in a very simple function for the specific case. This is one suitable higher-order function:
(defun tree-mapcan (function tree)
(if (listp tree)
(list (mapcan (lambda (elt) (tree-mapcan function elt))
tree))
(funcall function tree)))

How to get dotted pairs in Lisp?

I've searched google and other places for a while but I can't find out how to generate or create dotted pairs. I ask this because, I need to turn a list that looks like this:
(X Y Z)
To a list that is in this format:
((X . 1) (Y . 2) (Z . 3))
Where the numbers represent the index. I have a function that turns the list into the format of
(X 1 Y 2 Z 3)
Here is that function:
(defun listFormat (l)
(defun place-index (idx l)
(if (null l)
nil
(append (list (first l)) (list idx)
(place-index (+ idx 1) (rest l)))))
(place-index 1 l))
But I'm not sure how to get dotted pairs.
Thanks in advance
Your code has a very basic mistake:
(defun listFormat (l)
(defun place-index (idx l) ; <<<---- This DEFUN is wrong
(if (null l)
nil
(append (list (first l)) (list idx)
(place-index (+ idx 1) (rest l)))))
(place-index 1 l))
Don't nest DEFUN. That's just wrong. DEFUN defines a global function. Whenever you run listFormat, it redefines the GLOBAL function PLACE-INDEX. You may have seen similarly nested functions in SCHEME using DEFINE. In Common Lisp you should not use DEFUN for a nested local function.
In Lisp local functions are defined with FLET or LABELS (for recursive functions).
(defun listFormat (l)
(labels ((place-index (idx l)
(if (null l)
nil
(append (list (first l)) (list idx)
(place-index (+ idx 1) (rest l))))))
(place-index 1 l)))
Also Stackoverflow is the wrong place to solve your homework. Google searches is also the wrong way to learn Lisp programming.
I propose to use the good old way of reading an introductory book and using a reference.
Here is a basic introductory Lisp book for download: Common Lisp: A Gentle Introduction to Symbolic Computation.
Reference sheets: a small Common Lisp Quick Reference (PDF) and a more detailed Common Lisp Quick Reference.
Dotted pairs are called conses in Lisp.
See the real online reference for Common Lisp, the Common Lisp HyperSpec.
You want the else-branch to read:
(cons (cons (first l) idx) (place-index (+ idx 1) (rest l)))
And by the way, for the question itself, this code will do:
(defun listFormat (lst)
(loop for idx from 1
for item in lst
collect (cons item idx)))