Common Lisp: Using (let) for evaluating recursive function - recursion

So I wrote something that returns a maximal subset sum given a list of positive integers. However, I would like to use the (let) so that I make the code more efficient. I would like to know if or how that is possible.
(defun subset-sum1 (numbers capacity)
(subset-sum numbers capacity 0))
(defun subset-sum (numbers capacity counter)
(cond ((null numbers) counter)
((= counter capacity) counter) ;; return if counter 'hits' the capacity
((< capacity (+ (car numbers) counter))
(subset-sum (cdr numbers) capacity counter)) ;; cdr if car branch exceeds capacity
((<= (subset-sum (cdr numbers) capacity counter)
(subset-sum (cdr numbers) capacity (+ (car numbers) counter)))
(subset-sum (cdr numbers) capacity (+ (car numbers) counter))) ;; choose car
(t (subset-sum (cdr numbers) capacity counter)))) ;; choose cdr
The above code works fine in common lisp. But, I would like to do something like below, because I feel like using let will make the code better. But what I wrote goes into an infinite loop :(
This is an assignment for an introductory AI class... help out a novice please!
(defun subset-sum (numbers capacity counter)
(let ((exclude (subset-sum (cdr numbers) capacity counter))
(include (subset-sum (cdr numbers) capacity (+ (car numbers) counter))))
(cond ((null numbers) counter)
((= counter capacity) counter)
((< capacity (+ (car numbers) counter)) exclude)
((<= exclude include) include)
(t (exclude)))))

You get an infinite loop because of these lines:
(defun subset-sum (numbers capacity counter)
(let ((exclude (subset-sum (cdr numbers) capacity counter))
You keep calling subset-sum recursively, and it never terminates. Even when you get to the end of the list, and numbers is (), you keep going, because (cdr '()) is '(). You handled this in the original by checking (null numbers) (though it might be more idiomatic to use (endp numbers)). Now you can do something like:
(defun subset-sum (numbers capacity counter)
(if (endp numbers)
counter
(let ((exclude (subset-sum (cdr numbers) capacity counter))
;...
)
(cond ; ...
))))

Related

How can I make my average function tail recursive in Lisp

I am simply trying to make this average function to be tail recursive. I have managed to get my function to work and that took some considerable effort. Afterwards I went to ask my professor if my work was satisfactory and he informed me that
my avg function was not tail recursive
avg did not produce the correct output for lists with more than one element
I have been playing around with this code for the past 2 hours and have hit a bit of a wall. Can anyone help me to identify what I am not understanding here.
Spoke to my professor he was != helpful
(defun avg (aList)
(defun sumup (aList)
(if (equal aList nil) 0
; if aList equals nil nothing to sum
(+ (car aList) (sumup (cdr aList)) )
)
)
(if
(equal aList nil) 0
; if aList equals nil length dosent matter
(/ (sumup aList) (list-length aList) )
)
)
(print (avg '(2 4 6 8 19))) ;39/5
my expected results for my test are commented right after it 39/5
So this is what I have now
(defun avg (aList &optional (sum 0) (length 0))
(if aList
(avg (cdr aList) (+ sum (car aList))
(+ length 1))
(/ sum length)))
(print (avg '(2 4 6 8 19))) ;39/5
(defun avg (list &optional (sum 0) (n 0))
(cond ((null list) (/ sum n))
(t (avg (cdr list)
(+ sum (car list))
(+ 1 n)))))
which is the same like:
(defun avg (list &optional (sum 0) (n 0))
(if (null list)
(/ sum n)
(avg (cdr list)
(+ sum (car list))
(+ 1 n))))
or more similar for your writing:
(defun avg (list &optional (sum 0) (n 0))
(if list
(avg (cdr list)
(+ sum (car list))
(+ 1 n))
(/ sum n)))
(defun avg (lst &optional (sum 0) (len 0))
(if (null lst)
(/ sum len)
(avg (cdr lst) (incf sum (car lst)) (1+ len))))
You could improve your indentation here by putting the entire if-then/if-else statement on the same line, because in your code when you call the avg function recursively the indentation bleeds into the next line. In the first function you could say that if the list if null (which is the base case of the recursive function) you can divide the sum by the length of the list. If it is not null, you can obviously pass the cdr of the list, the sum so far by incrementing it by the car of the list, and then increment the length of the list by one. Normally it would not be wise to use the incf or 1+ functions because they are destructive, but in this case they will only have a localized effect because they only impact the optional sum and len parameters for this particular function, and not the structure of the original list (or else I would have passed a copy of the list).
Another option would be to use a recursive local function, and avoid the optional parameters and not have to compute the length of the list on each recursive call. In your original code it looks like you were attempting to use a local function within the context of your avg function, but you should use the "labels" Special operator to do that, and not "defun":
(defun avg (lst)
(if (null lst)
0
(labels ((find-avg (lst sum len)
(if (null lst)
(/ sum len)
(find-avg (cdr lst) (incf sum (car lst)) len))))
(find-avg lst 0 (length lst))))
I'm not 100% sure if your professor would want the local function to be tail-recursive or if he was referring to the global function (avg), but that is how you could also make the local function tail-recursive if that is an acceptable remedy as well. It's actually more efficient in some ways, although it requires more lines of code. In this case a lambda expression could also work, BUT since they do not have a name tail-recursion is not possibly, which makes the labels Special operator is useful for local functions if tail-recursion is mandatory.

Referencing variables in racket

I'm trying to write a simple procedure for finding the n:th prime but I don't think I understand how to reference variables correctly in racket.
What I want is for the inner procedure sieve-iter to add primes to the list primlst which is in the namespace of sieve but I get an infinite loop. My guess is that primlst within sieve-iter is causing issues.
(define (sieve n) ;; returns the n:th prime (n>0)
(let [(primlst '(2))
(cand 3)]
(define (sieve-iter i lst)
(cond ((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;prime
((= (length primlst) n) (car primlst)) ;;end
((= (modulo i (car lst)) 0) (sieve-iter (+ i 2) primlst)) ;;non-prime
(#t (sieve-iter n (cdr lst))))) ;;unclear if prime
(sieve-iter cand primlst)))
Any help is appreciated!
First of all, you shouldn't refer to primlist at all within the sieve-iter function. Instead, you should refer to lst.
Second of all, you appear to be mistaken on the effect of this expression:
(and (cons i primlst) (sieve-iter (+ i 2) primlst))
You seem to be interpreting that as meaning "Add i to the primlist and then start the next iteration."
(cons i primlist) changes nothing. Instead, it creates a new list consisting of primlist with i in front of it and then evaluates to that value. The original primlist (which should have been lst anyway) is left untouched.
Also, and is for Boolean logic, not for stringing commands together. It evaluates each of its subexpressions separately until it finds one that evaluates to #f and then it stops.
You should replace that whole expression with this:
(sieve-iter (+ i 2) (cons i lst))
...which passes the new list created by cons to the next run of sieve-iter.
Your trying to do too much in one function, let prime-iter just worry about the iteration to build up the list of primes. Make another internal function to recurse down the existing primes to test the new candidate.
(define (sieve n) ;; returns the n:th prime (n>0)
(define (sieve-iter i lst remaining)
(cond ;((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;should never be null, we are building the list up
((<= remaining 0) (car lst)) ;;checking length every time gets expensive added a variable to the function
((sieve-prime? i lst) ;;if prime add to lst and recurse on next i
(sieve-iter (+ i 2) (cons i lst) (- remaining 1)))
(else
(sieve-iter (+ i 2) lst remaining)))) ; else try next
(define (sieve-prime? i lst)
(cond ((null? lst) #t)
((= 0 (modulo i (car lst))) #f)
(else (sieve-prime? i (cdr lst)))))
(let ((primlst '(2)) ;;you generally don't modify these,
(cand 3)) ;mostly they just bind values to name for convenience or keep from having to re-calculate the same thing more than once
(sieve-iter cand primlst (- n 1))))
You could have used set! to modify primlist where it was before, but the procedure is no longer obviously a pure function.
There is another low-handing optimization possible here, when calling sieve-prime? filter the lst argument to remove values larger than the square root of i.

Finding the difference in an arithmetic progression in Lisp

I am totally new to Lisp.
How to find the difference between elements in an arithmetic progression series?
e.g.
(counted-by-N '(20 10 0))
Return -10
(counted-by-N '(20 10 5))
(counted-by-N '(2))
(counted-by-N '())
Returns Nil
In Python/C and other languages, it is very straightforward... Kinda stuck here in Lisp.
My pseudo algorithm would be something like this:
function counted-by-N(L):
if len(L) <= 1:
return Nil
else:
diff = L[second] - L[first]
for (i = second; i < len(L) - 1; i++):
if L[i+1] - L[i] != diff
return Nil
return diff
Current work:
(defun count-by-N (L)
(if (<= (length L) 1) Nil
(
(defvar diff (- (second L) (first L)))
; How to do the loop part?
))
)
(flet ((by-n (list &aux
(e1 (first list))
(e2 (second list))
(difference (and e1 e2 (- e2 e1))))
(and difference
(loop for (one two) on list
while (and one two)
when (/= (- two one) difference)
do (return-from by-n nil)))
difference))
(by-n '(20 10 0)))
or
(flet ((by-n (list &aux
(e1 (first list))
(e2 (second list))
(difference (and e1 e2 (- e2 e1))))
(when difference
(loop for (one two) on list
while (and one two)
when (/= (- two one) difference)
do (return-from by-n nil))
difference)))
(by-n '(20 10 0)))
As far as you said on the second answer the best choice you have to do this example is implement it recursively.
Example Using List Processing (good manners)
That way, you have some ways to do this example on the recursively and simple way:
(defun count-by-N-1 (lst)
(if (equal NIL lst)
NIL
(- (car (cdr lst)) (car lst))
)
(count-by-N-1 (cdr lst))
)
On this first approach of the function count-by-N-1 I am using the simple car and cdr instructions to simplify the basics of Common Lisp List transformations.
Example Using List Processing Shortcuts (best implementation)
However you can resume by using some shortcuts of the car and cdr instructions like when you want to do a a car of a cdr, like I did on this example:
(defun count-by-N-2 (lst)
(if (equal NIL lst)
NIL
(- (cadr lst) (car lst))
)
(count-by-N-2 (cdr lst))
)
If you have some problems to understand this kind of questions using basic instructions of Common Lisp List transformation as well as car and cdr, you still can choose the first, second and rest approach. However I recommend you to see some of this basic instructions first:
http://www.gigamonkeys.com/book/they-called-it-lisp-for-a-reason-list-processing.html
Example Using Accessors (best for understand)
(defun count-by-N-3 (lst)
(if (equal NIL lst)
NIL
(- (first (rest lst)) (first lst))
)
(count-by-N-3 (rest lst))
)
This last one, the one that I will explain more clearly since it is the most understandable, you will do a recursion list manipulation (as in the others examples), and like the others, until the list is not NIL it will get the first element of the rest of the list and subtract the first element of the same list. The program will do this for every element till the list is "clean". And at last returns the list with the subtracted values.
That way if you read and study the similarities between using first, second and rest approach against using car and cdr, you easily will understand the both two first examples that I did put here.
Here is my final answer of this question which uses recursion:
(defun diff (N)
(- (second N) (first N))
)
(defun count-by-N (L)
(cond
((null L) nil)
((= (length L) 1) nil)
((= (length L) 2) (diff L))
((= (diff L) (diff (rest L))) (count-by-N (rest L)))
(T nil)
)
)

Input a value to be used instead of (FDEFINITION 'COMP

clisp:
(defun sorted (seq comp)
(or
(< (length seq) 2)
(and (comp (car seq) (car seq))
(sorted (cdr seq) comp)
)
))
on ubuntu, run clisp :
(sorted '(1 3 4) #'<)
ERROR:USE-VALUE :R1 Input a value to be used instead of (FDEFINITION 'COMP).
how fix it?
There are quite a few things amiss in your code.
First, in Common Lisp, data and functions live in separate namespaces. For this reason, you cannot use (comp x y) to call the function referred to by the variable comp. You have to use the funcall function.
Second, you are comparing (car seq) with (car seq) - that is, with itself. You probably meant to say (car (cdr seq)), which refers to the second element in the list.
After these changes, the code works correctly:
(defun sorted (seq comp)
(or (< (length seq) 2)
(and (funcall comp (car seq) (car (cdr seq)))
(sorted (cdr seq) comp))))
* (sorted '(1 3 4) #'<)
T
* (sorted '(1 4 3) #'<)
NIL
Evaluating (length seq) on every iteration of your function is not efficient; to get the list's length, the system must go through the entire list. Effectively, your code will spend quadratic time doing a linear operation. It would be better to replace that with a simple end check.
Also, I would use the functions first and second instead of (car seq) and (car (cdr seq)), and rest instead of cdr. It is better to explicitly state in your code what you mean with it.
With these changes, the final code looks like this:
(defun sorted (seq comp)
(or (endp (rest seq))
(and (funcall comp (first seq) (second seq))
(sorted (rest seq) comp))))

Maximum of a list using recursion?

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

Resources