My task is to write function in lisp which finds maximum of a list given as argument of the function, by using recursion.I've tried but i have some errors.I'm new in Lisp and i am using cusp plugin for eclipse.This is my code:
(defun maximum (l)
(if (eq((length l) 1)) (car l)
(if (> (car l) (max(cdr l)))
(car l)
(max (cdr l))
))
If this isn't a homework question, you should prefer something like this:
(defun maximum (list)
(loop for element in list maximizing element))
Or even:
(defun maximum (list)
(reduce #'max list))
(Both behave differently for empty lists, though)
If you really need a recursive solution, you should try to make your function more efficient, and/or tail recursive. Take a look at Diego's and Vatine's answers for a much more idiomatic and efficient recursive implementation.
Now, about your code:
It's pretty wrong on the "Lisp side", even though you seem to have an idea as to how to solve the problem at hand. I doubt that you spent much time trying to learn lisp fundamentals. The parentheses are messed up -- There is a closing parenthesis missing, and in ((length l) 1), you should note that the first element in an evaluated list will be used as an operator. Also, you do not really recurse, because you're trying to call max (not maximize). Finally, don't use #'eq for numeric comparison. Also, your code will be much more readable (not only for others), if you format and indent it in the conventional way.
You really should consider spending some time with a basic Lisp tutorial, since your question clearly shows lack of understanding even the most basic things about Lisp, like the evaluation rules.
I see no answers truly recursive and I've written one just to practice Common-Lisp (currently learning). The previous answer that included a recursive version was inefficient, as it calls twice maximum recursively. You can write something like this:
(defun my-max (lst)
(labels ((rec-max (lst actual-max)
(if (null lst)
actual-max
(let ((new-max (if (> (car lst) actual-max) (car lst) actual-max)))
(rec-max (cdr lst) new-max)))))
(when lst (rec-max (cdr lst) (car lst)))))
This is (tail) recursive and O(n).
I think your problem lies in the fact that you refer to max instead of maximum, which is the actual function name.
This code behaves correctly:
(defun maximum (l)
(if (= (length l) 1)
(car l)
(if (> (car l) (maximum (cdr l)))
(car l)
(maximum (cdr l)))))
As written, that code implies some interesting inefficiencies (it doesn't have them, because you're calling cl:max instead of recursively calling your own function).
Function calls in Common Lisp are typically not memoized, so if you're calling your maximum on a long list, you'll end up with exponential run-time.
There are a few things you can do, to improve the performance.
The first thing is to carry the maximum with you, down the recursion, relying on having it returned to you.
The second is to never use the idiom (= (length list) 1). That is O(n) in list-length, but equivalent to (null (cdr list)) in the case of true lists and the latter is O(1).
The third is to use local variables. In Common Lisp, they're typically introduced by let. If you'd done something like:
(let ((tail-max (maximum (cdr l))))
(if (> (car l) tail-max)
(car l)
tail-max))
You would've had instantly gone from exponential to, I believe, quadratic. If in combination had done the (null (cdr l)) thing, you would've dropped to O(n). If you also had carried the max-seen-so-far down the list, you would have dropped to O(n) time and O(1) space.
if i need to do the max code in iteration not recursive how the code will be ??
i first did an array
(do do-array (d l)
setf b (make-array (length d))
(do (((i=0)(temp d))
((> i (- l 1)) (return))
(setf (aref b i) (car temp))
(setq i (+ i 1))
(setq temp (cdr temp))))
I made this, hope it helps and it is recursive.
(defun compara ( n lista)
(if(endp lista)
n
(if(< n (first lista))
nil
(compara n (rest lista)))))
(defun max_lista(lista)
(if (endp lista)
nil
(if(compara (first lista) (rest lista))
(first lista)
(max_lista(rest lista)))))
A proper tail-recursive solution
(defun maximum (lst)
(if (null lst)
nil
(maximum-aux (car lst) (cdr lst))))
(defun maximum-aux (m lst)
(cond
((null lst) m)
((>= m (car lst)) (maximum-aux m (cdr lst)))
(t (maximum-aux (car lst) (cdr lst)))))
(defun maxx (l)
(if (null l)
0
(if(> (car l) (maxx(cdr l)))
(car l)
(maxx (cdr l)))))
Related
I've been trying to tinker with this code to rewrite a "repeat" function using tail-end recursion but have gotten a bit stuck in my attempts.
(define (repeat n x)
(if (= n 0)
'()
(cons x (repeat (- n 1) x))))
This is the original "repeat" function. It traverses through 'n - 1' levels of recursion then appends 'x' into a list in 'n' additional recursive calls. Instead of that, the recursive call should be made and the 'x' should be appended to a list at the same time.
(define (repeat-tco n x)
(trace-let rec ([i 0]
[acc '()])
(if (= i n)
acc
(rec (+ i 1) (cons x acc)))))
This is the closest rewritten version that I've come up with which I believe follows tail-call recursion but I'm not completely sure.
Your repeat-tco function is indeed tail recursive: it is so because the recursive call to rec is in 'tail position': at the point where it's called, the function that is calling it has nothing left to do but return the value of that call.
[The following is just some perhaps useful things: the answer is above, but an answer which was essentially 'yes' seemed too short.]
This trick of taking a procedure p which accumulates some result via, say (cons ... (p ...)) and turning it into a procedure with an extra 'accumulator' argument which is then tail recursive is very common. A result of using this technique is that the results come out backwards: this doesn't matter for you because all the elements of your list are the same, but imagine this:
(define (evens/backwards l)
(let loop ([lt l]
[es '()])
(if (null? lt)
es
(loop (rest lt)
(if (even? (first lt))
(cons (first lt) es)
es)))))
This will return the even elements of its arguments, but backwards. If you want them the right way around, a terrible answer is
(define (evens/terrible l)
(let loop ([lt l]
[es '()])
(if (null? lt)
es
(loop (rest lt)
(if (even? (first lt))
(append es (list (first lt)))
es)))))
(Why is it a terrible answer?) The proper answer is
(define (evens l)
(let loop ([lt l]
[es '()])
(if (null? lt)
(reverse es)
(loop (rest lt)
(if (even? (first lt))
(cons (first lt) es)
es)))))
I'm making my way through the book The Little Schemer to start to learn to think in Lisp. As you get into it and really cover the use of lambdas, the 'remove' procedure is written in the following general form, which returns a remove procedure for arbitrary test test?:
(define rember-f
(lambda (test?)
(lambda (a l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l)
((rember-f test?) a (cdr l))))))))
I understand how this works just fine, but a plain reading of it suggests that at each recursive step, it is the procedure rember-f that is called again to generate a new enclosed procedure. This would mean when you call your returned procedure on a list, it calls rember-f to generate the same procedure again anew and then that new one is what is called for recursion (if that is not clear see my fix below). I understand that this may be optimized away, but in lieu of not knowing whether it is (and also in attempting to get my head around this syntax anyway), I managed after some experimentation to move the recursion to the procedure itself rather than the enclosing procedure as follows:
(define rember-f
(lambda (test?)
(define retfun
(lambda (a l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (retfun a (cdr l)))))))
retfun))
I have verified that this works as expected. The return value is a procedure that removes the first element of a list (arg 2) matching a value (arg 1). It looks to me like this one only calls rember-f once, which guarantees it only generates one enclosed procedure (this time with a name, retfun).
This is actually interesting to me because unlike the usual tail call optimization, which is about not consuming space on the call stack and so making recursion about as efficient as iteration, in this case the compiler would have to determine that (rember-f test?) is the enclosing procedure scope unmodified and so replace it with the same return value, which is the anonymous (lambda (a l) ...). It would not surprise me at all to learn that the interpreter / compiler does not catch this.
Yes, I know that scheme is a specification and there are many implementations, which get the various functional programming optimizations right to differing degrees. I am currently learning by experimenting in the guile REPL, but would be interested in how different implementations compare on this issue.
Does anyone know how Scheme is supposed to behave in this instance?
You are right to be concerned about the additional repeated lambda abstractions. For example you wouldn't write this, would you?
(cond ((> (some-expensive-computation x) 0) ...)
((< (some-expensive-computation x) 0) ...)
(else ...))
Instead we bind the result of some-expensive-computation to an identifier so we can check multiple conditions on the same value -
(let ((result (some-expensive-computation x)))
(cond ((> result 0) ...)
((< result 0) ...)
(else ...)))
You discovered the essential purpose of so-called "named let" expressions. Here's your program -
(define rember-f
(lambda (test?)
(define retfun
(lambda (a l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (retfun a (cdr l)))))))
retfun))
And its equivalent using a named-let expression. Below we bind the let body to loop, which is a callable procedure allowing recursion of the body. Notice how the lambda abstractions are used just once, and the inner lambda can be repeated without creating/evaluating additional lambdas -
(define rember-f
(lambda (test?)
(lambda (a l)
(let loop ; name, "loop", or anything of your choice
((l l)) ; bindings, here we shadow l, or could rename it
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (loop (cdr l))))))))) ; apply "loop" with args
Let's run it -
((rember-f eq?) 'c '(a b c d e f))
'(a b d e f)
The syntax for named-let is -
(let proc-identifier ((arg-identifier initial-expr) ...)
body ...)
Named-let is a syntax sugar of a letrec binding -
(define rember-f
(lambda (test?)
(lambda (a l)
(letrec ((loop (lambda (l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (loop (cdr l))))))))
(loop l)))))
((rember-f eq?) 'c '(a b c d e f))
'(a b d e f)
Similarly, you could imagine using a nested define -
(define rember-f
(lambda (test?)
(lambda (a l)
(define (loop l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (loop (cdr l))))))
(loop l))))
((rember-f eq?) 'c '(a b c d e f))
'(a b d e f)
PS, you you can write '() in place of (quote ())
Both procedures have the same asymptotic time complexity. Let's consider the evaluation of ((rember-f =) 1 '(5 4 3 2 1 0)).
A partial evaluation proceeds as follows:
((rember-f =) 1 '(5 4 3 2 1 0))
((lambda (a l)
(cond
((null? l) (quote ()))
((= (car l) a) (cdr l))
(else (cons (car l)
((rember-f =) a (cdr l)))))) 1 '(5 4 3 2 1 0))
(cons 5 ((rember-f = 1 '(4 3 2 1 0))))
Note that the creation of the temporary lambda procedure takes O(1) time and space. So it doesn't actually add any substantial overhead to the cost of calling the function. At best, factoring out the function will lead to a constant-factor speedup and the use of a constant amount less of memory.
But how much memory does it really take to make a closure? It turns out it takes very little memory. A closure consists of a pointer to the environment and a pointer to compiled code. Basically, creating the closure requires as much time and space as making a cons cell. So even though it looks like we're using a lot of memory when I show the evaluation, very little memory and very little time is actually used to make and store the lambda.
So essentially, by factoring out the recursive function, you've allocated a single cons cell rather than writing code which allocates that cons cell one time per recursive call.
For more information on this, see Lambda is cheap, and Closures are Fast.
to start to learn to think in Lisp
That book is not about thinking in lisp, but about recursive thinking, which is one of the ways of computation discovered in the 20th century by Goedel, Herbrand, Rozsa Peter.
Does anyone know how Scheme is supposed to behave in this instance?
After you finish the little lisper you should take the SICP, which will make you understand what kind of decisions an implementation of a language can make. You mean, how different implementations act. To understand their implementation decision, the best step to do is to learn it from SICP. Take care, unless you are already a certified computer science graduate, this texbook will take you a few years to master, if you study it each day. If you are already a graduate, it will take you only about 1 year to master.
I want to append the element b to the list a (let's say (a1, a2, ... an)), e.g. appending the number 3 to (1 2) gives (1 2 3)
So far I've been doing
(append a (list b)), which is kind of long and inelegant, so I wonder if there's a "better" way...
Are you building a list piecemeal, an item at a time? If so, the idiomatic way to do this is to build the list backward, using cons, and then reversing the final result:
(define (map-using-cons-and-reverse f lst)
(let loop ((result '())
(rest lst))
(if (null? rest)
(reverse result)
(loop (cons (f (car rest)) (cdr rest))))))
Alternatively, if your list-building is amenable to a "right-fold" recursive approach, that is also idiomatic:
(define (map-using-recursion f lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (f (car rest)) (recur (cdr rest))))))
The above code snippets are just for illustrating the solution approach to take in the general case; for things that are directly implementable using fold, like map, using fold is more idiomatic:
(define (map-using-cons-and-reverse f lst)
(reverse (foldl (lambda (item result)
(cons (f item) result))
'() lst)))
(define (map-using-recursion f lst)
(foldr (lambda (item result)
(cons (f item) result))
'() lst))
How frequent do you have to append to the end?
If you want to do it a lot (more than cons'ing to the front), then you are doing it wrong. The right way is to flip things around: think that cons put things to the back, first retrieves the last element, rest retrieves everything but last, etc. Then, you can use list normally.
However, if you want to put things to the end of the list as frequent as to cons things to the front, then this is the best that you can do with one list. You could write a function to wrap what you consider "inelegant". Traditionally it's called snoc (backward cons)
(define (snoc lst e) (append lst (list e)))
Or if you prefer to implement the whole thing by yourself:
(define (snoc lst e)
(cond
[(empty? lst) (list e)]
[(cons? lst) (cons (first lst) (snoc (rest lst) e))]))
Note that both approaches have the same time complexity: O(n) where n is length of the list.
But if you want it to be efficient, you can use a data structure called double-ended queue, which is very efficient (constant time per operation). See http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf for more details.
I am watching SICP video lectures and i came to a section where tutors are showing procedures to work with lists, so, here is one of them:
(define (map p l)
(if (null? l)
(list)
(cons (p (car l))
(map p (cdr l)))))
What i want to ask is: is there a way to define map in iterative way, or that cons requires lazy evaluation to be executed right?
You original code is almost tail recursive.. the only thing that makes it not is the cons part. If Scheme had equal requirement for having TRMC optimization as it has TCO requirement you could leave your code as is and the implementation would have made it tail recursive for you.
Since it isn't a requirement we need to do our own TRMC optimization. Usually when iterating a list in a loop and having it tail recursive by using an accumulator you get the result in the opposite order, thus you can do linear update reverse:
(define (map proc lst)
(let loop ((lst lst) (acc '()))
(cond ((null? lst) (reverse! acc) acc)
(else (loop (cdr lst)
(cons (proc (car lst)) acc))))))
Or you can do it all in one pass:
(define (map proc lst)
(define head (list 1))
(let loop ((tail head) (lst lst))
(cond ((null? lst) (cdr head))
(else (set-cdr! tail (list (proc (car lst))))
(loop (cdr tail) (cdr lst))))))
Now in both cases you mutate only the structure the procedure has itself created, thus for the user it might as well be implemented in the same manner as your example.
When you use higher order procedures like map from your implementation it could happen it has been implemented like this. It's easy to find out by comparing performance on the supplied map with the different implementations with a very long list. The difference between the executions would tell you if it's TRMCO or how the supplied map probably has been implemented.
You need to embrace recursion in order to appreciate SICP and Scheme in general, so try to get used to it, you will appreciate it later, promised.
But yes, you can:
(define (iterative-map f lst)
(define res null)
(do ((i (- (length lst) 1) (- i 1))) ((= i -1))
(set! res (cons (f (list-ref lst i)) res)))
res)
(iterative-map (lambda (x) (+ x 1)) '(1 3 5))
=> '(2 4 6)
but using set! is considered bad style if avoidable.
In Racket you have a different set of loops that are more elegant:
(define (for-map f lst)
(for/list ((i lst))
(f i)))
(for-map add1 '(1 3 5))
=> '(2 4 6)
Can someone explain to me how the recursion works in the following function? Specifically, I am interested in what happens when the function reaches its base case. Also, why is a named let used in this code? (I am not familiar with named lets)
(define (unzip list-of-pairs)
(if (null? list-of-pairs)
(cons '() '())
(let ((unzipped (unzip (cdr list-of-pairs))))
(cons (cons (car (car list-of-pairs)) (car unzipped))
(cons (cdr (car list-of-pairs)) (cdr unzipped))))))
The procedure shown doesn't have anything special about it, you're just iterating over a list of this form:
'((1 . 2) (3 . 4) (5 . 6))
The only "weird" part is that the output is building two lists instead of the usual single list. As you know, when we're building a single list as output the base case is this:
(if (null? lst) '() ...)
But here, given that we're simultaneously building two lists, the base case looks like this:
(if (null? lst) (cons '() '()) ...)
The code in the question is not using a named let, it's just a plain old garden-variety let, there's nothing special about it. It's useful because we want to call the recursion only once, given that we need to obtain two values from the recursive call.
If we don't mind being inefficient, the procedure can be written without using let, at the cost of calling the recursion two times at each step:
(define (unzip list-of-pairs)
(if (null? list-of-pairs)
(cons '() '())
(cons (cons (car (car list-of-pairs))
(car (unzip (cdr list-of-pairs))))
(cons (cdr (car list-of-pairs))
(cdr (unzip (cdr list-of-pairs)))))))
Of course, the advantage of using let is that it avoids the double recursive call.