I need to be able to compare two cars of a list to sort them im LISP.
Lists '(e d) (a b)
I want to compare the cars (e and a). This works using eql. If they don't match, I want to order the lists alphabetically, so (a b) (e d).
I'm missing the part where I can see which character is 'bigger', so the check if e or a should come first. I've tried converting them to ascii codes, but that doesn't work for (car a). Using arithmetic operators such as '<' and '>' also doesn't work. Does anyone have an idea on how to do this?
Use string> without symbol-name:
CL-USER 6 > (string> 'a 'b)
NIL
CL-USER 7 > (string< 'a 'b)
0
For the sake of completeness, here is how you should use it inside sort to achieve desired result (sort is destructive- modifies used sequence, so I also used copy-tree to avoid that effect):
(let ((data '((e d) (a b))))
(sort (copy-tree data)
(lambda (x y) (string< (car x) (car y)))))
((A B) (E D))
A symbol is distinct from a string.
CL-USER> (symbol-name 'foo)
"FOO"
A string (a sequence of characters) can be compared in the manner you seem to be interested in.
CL-USER> (string> "FOO" "BOO")
0
CL-USER> (string< "FOO" "BOO")
NIL
Related
I tried to return every elements in the list that doesn’t match with "a".
Here is what i tried so far.
(defun removeA (arr)
(cond((null arr) nil)
((if (listp (car arr))
(or (removeA (car arr)) (removeA (cdr arr)))
(if (eql 'a (car arr))
(removeA (cdr arr))
(cons (car arr) (removeA (cdr arr)))
)
))
)
)
(print (removeA '(a (a) (v a e) (a a) d)))
here is the output: (V E)
i need help on why its not printing "D" as well
My Solution:
(defun removeA (ls)
(let ((withoutA
(if (consp ls)
(remove-if #'(lambda (l) (equal l 'a)) ls)
ls)))
(if (consp ls)
(mapcar #'removeA withoutA)
ls)))
(print
(removeA '(a (a) (v a e) (a a) d)))
That prints (NIL (V E) NIL D).
The NILs representing the empty lists.
The specification for the program appears to be this:
Input is a list, of individual items or lists
If individual item, remove it if it is the value 'a'
If a list, remove all items within it with value 'a'
My first reaction is to map a function over the input list, using mapcar or something similar - if you are using car or cdr it's worth checking to see if there is a higher level way of doing the same thing.
However, I am advised that using mapcar is inefficient, and a better approach is to use loop. The loop construct is a macro, with loop in the function position, followed by an English-style series of words.
(defun remove-a (lst)
(loop
for x in lst
if (listp x) collect (remove-if #'isa-p x)
else collect (if (isa-p x) nil x)))
(defun isa-p (val) (equal val 'a))
Hence:
(remove-a '(a (a) (v a e) (a a) d))
(NIL NIL (V E) NIL D)
The result can be flattened into a single list using Alexandria:flatten, which you need to load first with (ql:quicklisp 'Alexandria).
If you want to use car and cdr, my comments are as follows.
What you are supplying as an input is a list, but you call it arr, suggesting an array; arrays are very different things in Common Lisp.
You've got your if and cond the wrong way around. The function cond is like switch-case in other languages. You want to check for an empty list with if, before considering the various possibilities with cond.
You are using print to show the results. This is not necessary if you are using a REPL. (print a) and a are equivalent in a REPL.
(defun foo (in i out)
(if (>= i 0)
(progn
(append (list (intern (string (elt in i)))) out)
(print output)
(foo in (- i 1) out )
)
(out)
)
)
(print (foo "abcd" (- (length "abcd") 1) (list)))
I am trying to return this string as (a b c d). But it does return nil as output. What do I do wrong here? Thanks
I don’t know what this has to do with appending. I think your desired output is also weird and you shouldn’t do what you’re doing. The right object for a character is a character not a symbol. Nevertheless, a good way to get the list (a b c d) is as follows:
CL-USER> '(a b c d)
Interning symbols at runtime is weird so maybe you would like this:
(defconstant +alphabet+ #(a b c d e f g h i j k l m n o p q r s t u v w x y z))
(defun foo (seq)
(map 'list
(lambda (char)
(let ((index (- (char-code char) (char-code #\a))))
(if (< -1 index (length +alphabet+))
(svref +alphabet+ index)
(error "not in alphabet: ~c" char))))
seq))
You have just some minor mistakes. First, we need to get rid of output and (output); these bear no relation to the code. It seems you were working with a variable called output and then renamed it to out without fixing all the code. Moreover, (output) is a function call; it expects a function called output to exist.
Secondly, the result of append must be captured somehow; in the progn you're just discarding it. Here is a working version:
(defun foo (in i out)
(if (>= i 0)
(foo in (1- i) (cons (intern (string (elt in i))) out))
out))
Note also that instead of your (append (list X) Y), I'm using the more efficient and idiomatic (cons X Y). The result of this cons operation has to be passed to foo. The out argument is our accumulator that is threaded through the tail recursion; it holds how much of the list we have so far.
I.e. we can't have (progn <make-new-list> (foo ... <old-list>)); that just creates the new list and throws it away, and then just passes the old list to the recursive call. Since the old list initially comes as nil, we just keep passing along this nil and when the index hits zero, that's what pops out. We need (foo .... <make-new-list>), which is what I've done.
Tests:
[1]> (foo "" -1 nil)
NIL
[2]> (foo "a" 0 nil)
(|a|)
[3]> (foo "ab" 1 nil)
(|a| |b|)
[4]> (foo "abcd" 3 nil)
(|a| |b| |c| |d|)
[5]> (foo "abcd" 3 '(x y z))
(|a| |b| |c| |d| X Y Z)
Lastly, if you want the (|a| |b| |c| |d|) symbols to appear as (a b c d), you have to fiddle withreadtable-case.
Of course:
[6]> (foo "ABCD" 3 nil)
(A B C D)
I'm trying to implement the Towers of Hanoi.I'm not printing out anything between my recursive calls yet, but I keep getting an error saying
'('(LIST) 'NIL 'NIL) should be a lambda expression
I've read that the reason this happens is because of a problem with the parenthesis, however I cannot seem to find what my problem is. I think it's happening in the pass-list function when I am trying to call the hanoi function. My code:
(defun pass-list(list)
(hanoi('('(list)'()'())))
)
(defun hanoi ('('(1) '(2) '(3)))
(hanoi '('(cdr 1) '(cons(car 1) 2) '(3)))
(hanoi '('(cons(car 3)1) '(2)'(cdr 3)))
)
This code has many syntax problems; there are erroneous quotes all over the place, and it looks like you're trying to use numbers as variables, which will not work. The source of the particular error message that you mentioned comes from
(hanoi('('(list)'()'())))
First, understand that the quotes in 'x and '(a b c) are shorthand for the forms (quote x) and (quote (a b c)), and that (quote anything) is the syntax for getting anything, without anything being evaluated. So '(1 2 3) gives you the list (1 2 3), and '1 gives you 1. quote is just a symbol though, and can be present in other lists, so '('(list)'()'()) is the same as (quote ((quote (list)) (quote ()) (quote ()))) which evaluates to the list ((quote (list)) (quote ()) (quote ())). Since () can also be written nil (or NIL), this last is the same as ('(list) 'NIL 'NIL). In Common Lisp, function calls look like
(function arg1 arg2 ...)
where each argi is a form, and function is either a symbol (e.g., list, hanoi, car) or a list, in which case it must be a lambda expression, e.g., (lambda (x) (+ x x)). So, in your line
(hanoi('('(list)'()'())))
we have a function call. function is hanoi, and arg1 is ('('(list)'()'())). But how will this arg1 be evaluated? Well, it's a list, which means it's a function application. What's the function part? It's
'('(list)'()'())
which is the same as
'('(list 'NIL 'NIL))
But as I just said, the only kind of list that can be function is a lambda expression. This clearly isn't a lambda expression, so you get the error that you're seeing.
I can't be sure, but it looks like you were aiming for something like the following. The line marked with ** is sort of problematic, because you're calling hanoi with some arguments, and when it returns (if it ever returns; it seems to me like you'd recurse forever in this case), you don't do anything with the result. It's ignored, and then you go onto the third line.
(defun pass-list(list)
(hanoi (list list) '() '()))
(defun hanoi (a b c)
(hanoi (rest a) (cons (first a) b) c) ; **
(hanoi (cons (first c) a) b (rest c)))
If hanoi is supposed to take a single list as an argument, and that list is supposed to contain three lists (I'm not sure why you'd do it that way instead of having hanoi take just three arguments, but that's a different question, I suppose), it's easy enough to modify; just take an argument abc and extract the first, second, and third lists from it, and pass a single list to hanoi on the recursive call:
(defun hanoi (abc)
(let ((a (first abc))
(b (second abc))
(c (third abc)))
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))
I'd actually probably use destructuring-bind here to simplify getting a, b, and c out of abc:
(defun hanoi (abc)
(destructuring-bind (a b c) abc
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))
I have the following filter function that filters out a list, x, that doesn't satisfy the function f.
For example, I call (filter 'evenp '(0 1 2 3)) and get back (NIL 1 NIL 3). But this is exactly my problem. How do I make it so that I just get back (1 3) ?
(defun filter (f x)
(setq h (mapcar #'(lambda (x1)
(funcall f x1))
x))
(mapcar #'(lambda (a b)
(cond ((null a) b)))
h x))
i.e. the problem is right here: (lambda (a b) (cond ( (null a) b) ) ) In my cond I don't have a t , or else statement, so shouldn't it just stop right there and not return nil ? How do I make it "return" nothing, not even nil, if the (cond ( (null a) b) ) isn't satisfied?
Much appreciated. :)
Based on this question it would be:
(remove-if #'evenp '(0 1 2 3))
Ignoring the other questions raised by this post, I'll say that mapcar will always return something for each thing it's mapping over, so you can't use another mapcar to clean up the NILs there. This is what mapcar does -- it walks over the item (or items, if mapping on multiple lists, as your second attempted mapcar does) and collects the result of calling some function on those arguments.
Instead, in this situation, if you had to use mapcar for some reason, and didn't want the NILs, you could use the remove function, i.e. (remove nil (mapcar ...))
Since #stark's answer is posted above, I'll say that the remove-if function there is essentially what you're trying to implement here. (That's where the question of whether or not this is for homework becomes most relevant.)
To answer the more general question of how to splice an arbitrary number of items (including none at all) into the result, mapcan (which is semantically mapcar + append) is useful for that:
(defun filter (f xs)
(mapcan (lambda (x)
(if (funcall f x)
(list x)
nil))
xs))
mapcan is also useful when you want to map an item to multiple results:
(defun multi-numbers (xs)
(mapcan (lambda (x) (list x (+ x x) (* x x))) xs))
(multi-numbers (list 1 2 3))
;=> (1 2 1 2 4 4 3 6 9)
I have a list of elements '(a b c) and I want to find if (true or false) x is in it, where x can be 'a or 'd, for instance. Is there a built in function for this?
If you need to compare using one of the build in equivalence operators, you can use memq, memv, or member, depending on whether you want to look for equality using eq?, eqv?, or equal?, respectively.
> (memq 'a '(a b c))
'(a b c)
> (memq 'b '(a b c))
'(b c)
> (memq 'x '(a b c))
#f
As you can see, these functions return the sublist starting at the first matching element if they find an element. This is because if you are searching a list that may contain booleans, you need to be able to distinguish the case of finding a #f from the case of not finding the element you are looking for. A list is a true value (the only false value in Scheme is #f) so you can use the result of memq, memv, or member in any context expecting a boolean, such as an if, cond, and, or or expression.
> (if (memq 'a '(a b c))
"It's there! :)"
"It's not... :(")
"It's there! :)"
What is the difference between the three different functions? It's based on which equivalence function they use for comparison. eq? (and thus memq) tests if two objects are the same underlying object; it is basically equivalent to a pointer comparison (or direct value comparison in the case of integers). Thus, two strings or lists that look the same may not be eq?, because they are stored in different locations in memory. equal? (and thus member?) performs a deep comparison on lists and strings, and so basically any two items that print the same will be equal?. eqv? is like eq? for almost anything but numbers; for numbers, two numbers that are numerically equivalent will always be eqv?, but they may not be eq? (this is because of bignums and rational numbers, which may be stored in ways such that they won't be eq?)
> (eq? 'a 'a)
#t
> (eq? 'a 'b)
#f
> (eq? (list 'a 'b 'c) (list 'a 'b 'c))
#f
> (equal? (list 'a 'b 'c) (list 'a 'b 'c))
#t
> (eqv? (+ 1/2 1/3) (+ 1/2 1/3))
#t
(Note that some behavior of the functions is undefined by the specification, and thus may differ from implementation to implementation; I have included examples that should work in any R5RS compatible Scheme that implements exact rational numbers)
If you need to search for an item in a list using an equivalence predicate different than one of the built in ones, then you may want find or find-tail from SRFI-1:
> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)
Here's one way:
> (cond ((member 'a '(a b c)) '#t) (else '#f))
#t
> (cond ((member 'd '(a b c)) '#t) (else '#f))
#f
member returns everything starting from where the element is, or #f. A cond is used to convert this to true or false.
You are looking for "find"
Basics - The simplest case is just (find Entry List), usually used as a predicate: "is Entry in List?". If it succeeds in finding the element in question, it returns the first matching element instead of just "t". (Taken from second link.)
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html
-or-
http://www.apl.jhu.edu/~hall/Lisp-Notes/Higher-Order.html
I don't know if there is a built in function, but you can create one:
(define (occurrence x lst)
(if (null? lst) 0
(if (equal? x (car lst)) (+ 1 (occurrence x (cdr lst)))
(occurrence x (cdr lst))
)
)
)
Ỳou will get in return the number of occurrences of x in the list. you can extend it with true or false too.
(define (member? x list)
(cond ((null? list) #f)
((equal? x (car list)) #t)
(else (member? x (cdr list)))))
The procedure return #t (true) or #f (false)
(member? 10 '(4 2 3))
output is #f