Return value in Lisp - recursion

So i started learning Lisp yesterday and started doing some problems.
Something I'm having a hard time doing is inserting/deleting atoms in a list while keeping the list the same ex: (delete 'b '(g a (b) l)) will give me (g a () l).
Also something I'm having trouble with is this problem.
I'm suppose to check if anywhere in the list the atom exist.
I traced through it and it says it returns T at one point, but then gets overriden by a nil.
Can you guys help :)?
I'm using (appear-anywhere 'a '((b c) g ((a))))
at the 4th function call it returns T but then becomes nil.
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T (appear-anywhere a (car l))(appear-anywhere a (cdr l)))))

Let's look at one obvious problem:
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T (appear-anywhere a (car l))(appear-anywhere a (cdr l)))))
Think about the last line of above.
Let's format it slightly differently.
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T
(appear-anywhere a (car l))
(appear-anywhere a (cdr l)))))
The last three lines: So as a default (that's why the T is there) the last two forms will be computed. First the first one and then the second one. The value of the first form is never used or returned.
That's probably not what you want.
Currently your code just returns something when the value of a appears anywhere in the rest of the list. The first form is never really used.
Hint: What is the right logical connector?

Related

Sort an element and put it in a variable

I have fowling task:
Write a recursive function SORT-LIST which, from a list of any number of "apples" and "peas", sorts out the "apples" and stores them in an optional variable and at the end returns the contents of this optional variable.
I have no idea how to fix ist. That's my beginning. Maybe there is someone who could help me. Thanks a lot!!
(defun sort-list (x l)
(cond ((null l) nil))
((equal (first l) x)
(cons (first l) (sort-list x (rest l))))
((sort-list x (rest l))))
The name is misleading. It is not sort but actually a filter.
(defun applep (x)
"something looking whether x is an apple or not")
(defun my-filter (pred l &optionals (acc '()))
(cond ((null l) (nreverse acc))
((funcall pred (car l)) (my-filter pred (cdr l) (cons (car l) acc)))
(t (my-filter pred (cdr l) acc))))
Which is in-built in lisps - so even without defining it, you could run:
(filter #'applep l)

Palindrome check with recursion in Lisp

I have developed code to check through input to see if it is a palindrome or not but I am having difficulty figuring out how to print the output. I want the output to return "t" if the input is a palindrome and "nil" if not. Also a challenge that I wanted to give myself was to not use the reverse function so thats why my code is not as simple as it could be. Thanks in advance.
(defun palindromep(l)
(cond ((null l) nil (write nil))
(t (append (list (car l)) (palindromep (cdr l)) (list (car l) )))))
(palindromep '(a b b a))
(terpri)
(palindromep '(a b c b a))
(terpri)
(palindromep '(a b c))
(terpri)
(palindromep '(a (d e) (d e) a))
(terpri)
(palindromep '(a (d e) (e d) a))
Firstly, an empty list is a palindrome! If we reverse it, we get the same empty list.
Secondly, Lisp functions don't print their result values; they return these values.
In an interactive session, it is the listener which prints the resulting value(s) that emerge from the expression being evaluated. That expression itself doesn't have to print anything.
Therefore, we begin like this:
(defun palindromep (l)
(cond
((null l) t) ;; the empty list is a palindrome: yield true.
Note, by the way, that if we write this:
((null l) nil t) ;; the empty list is a palindrome: yield true.
that doesn't do anything. The extra nil expression is evaluated, producing nil, which is thrown away. The Lisp compiler will completely eliminate that.
What if the list is not a list at all, but an atom other than nil? Let's just go with that being a palindrome. A clarification of requirements is needed, though:
((atom l) t)
Now we know we are dealing with a non-empty list. If it has exactly one item, then it is a palindrome:
((null (cdr l)) t)
Now we know we are dealing with a list of two or more items. That is a palindrome if the first and last items are the same, and if the items in between them form a palindrome.
(t (let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior))))))
The whole thing:
(defun palindromep (l)
(cond
((null l) t)
((atom l) t)
((null (cdr l)) t)
(t (let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior))))))
Code golfing: in the cond construct described by ANSI CL, a clause is permitted to have just one form. If that forms yields a true value, then that value is returned. Thus we can remove the t's:
(defun palindromep (l)
(cond
((null l)) ;; t removed
((atom l)) ;; likewise
((null (cdr l))) ;; likewise
(t (let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior))))))
Documentation about the functions ldiff and last can be found here.
Further golfing: if we have this pattern (cond (A) (B) ... (t Z)) we can just replace it by (or A B ... Z):
(defun palindromep (l)
(or (null l)
(atom l)
(let* ((first (car l))
(rest (cdr l))
(tail (last l))
(interior (ldiff rest tail)))
(and (eql first (car tail)) (palindromep interior)))))
cond is like a generalization of or that can specify an alternative result value for the each terminating true case.
To go on with code-golfing, since t or nil is expected, you can use only or and nil to express conditionals (and using short-circuitry of or and nil expressions).
Also it is good to be able to determine a :test keyword - since you want to control the crucial testing behavior.
To be able to use also inner lists, one could e.g. use equalp or even a custom comparison function.
(defun palindromep (l &key (test #'equalp))
(or (null l) (and (funcall test (car l) (car (last l)))
(palindromep (butlast (cdr l)) :test test))))
This evaluates
(palindromep '(a (d e) (d e) a))
as t but
(palindromep '(a (d e) (e d) a))
as nil.
Well, it is maybe a philosophical question, whether the latter should be t and the former nil.
To revert that behavior, we could write a custom testing function.
Like this:
(defun reverse* (l &optional (acc '()))
(cond ((null l) acc)
((atom (car l)) (reverse* (cdr l) (cons (car l) acc)))
(t (reverse* (cdr l) (cons (reverse* (car l) '()) acc)))))
(defun to-each-other-symmetric-p (a b)
(cond ((and (atom a) (atom b)) (equalp a b))
(t (equalp a (reverse* b)))))
Well, I use here some kind of a reverse*.
Then if one does:
(palindromep '(a (d e) (d e) a) :test #'to-each-other-symmetric-p) ;; NIL
;; and
(palindromep '(a (d e) (e d) a) :test #'to-each-other-symmetric-p) ;; T
Just to complete the other answers, I would like to point out that not using reverse will not only complicate your code enormously, but also make it far more inefficient. Just compare the above answers with the classic one:
(defun palindromep (l)
(equal l (reverse l)))
reverse is o(l), i.e. it takes time proportional to the length of the list l, and so does equal. So this function will run in o(l). You can't get faster than this.

Why is this function returning true when it should be returning false?

So, I have this helper function that checks to see if there is a reflexive relationship between a list and a list of pairs.
(define helper
(lambda (L S)
(cond
((if (equal? L '()) #f ;; here, when L equals empty list, it should return #f, but somehow it returns #t even if L is '().
(if (equal? S (car (car L)))
(if (list-equal? (car L))#t
(helper (cdr L) S))
(helper (cdr L) S))))
)))
However, the part where it checks if L is an empty list returns true even if the list is an empty list, allowing my other function to return true.
I've been stumped trying to figure out why its returning #t instead of #f for hours. Please help me figure out what's making this happen.
Oh and I'm using Dr.Racket version 6.12.
EDIT: more clearly, I would like the function to return #f when L is '() as a base case so that the function doesn't need to do anymore recursion.
You put if forms within cond which is quite superfluous.
So your mistake was for sure your lack of understanding of the cond syntax.
Remember cond syntax goes like:
(cond (condition1 what-to-do-if-condition1-is-true)
(condition2 what-to-do-if-condition2-is-true)
( ... ... )
(else what-to-do-if-none-of-the-conditions-listed-above-evaluated-to-true))
So I formed your expression accordingly to:
(define helper
(lambda (L S)
(cond ((equal? L '()) #f)
((and (equal? S (car (car L))) (list-equal? (car L))) #t)
(else (helper (cdr L) S)))))
Since you didn't gave definition for list-equal? - I cannot run this code for testing.
You have nested if in cond. Lets rewrite you code som something identical:
(define helper
(lambda (L S)
(let ((result
(if (equal? L '())
#f
(if (equal? S (car (car L)))
(if (list-equal? (car L))
#t
(helper (cdr L) S))
(helper (cdr L) S)))))
(cond
(result result)
(else 'implementation-defined-value)))))
A cond will return a implementation defined value as the else clause should none of the previous predicates hit. Since your base casse returns #f it goes to the default else case.
Since the other answer show the code with cond, here is the same with if:
(define helper
(lambda (L S)
(if (equal? L '())
#f
(if (and (equal? S (car (car L)))
(list-equal? (car L)))
#t
(helper (cdr L) S)))))
You can also write this only with and and or:
(define helper
(lambda (L S)
(and (pair? L)
(or (and (equal? S (car (car L)))
(list-equal? (car L)))
(helper (cdr L) S)))))

Member function for nested list in Scheme

Can someone show me the error in this code please?
I want to generalize the member function to support nested lists. I need to search thing inside the nested list and return the rest of the list when I found thing. I don't really understand whats wrong with the code below.
(define (memberk thing lis)
(cond
((null? lis) #f)
((list? (car lis))
(cons (memberk thing (car lis))
(memberk thing (cdr lis))))
(else
(if (equal? (car lis) thing)
lis
(memberk thing (cdr lis))))))
Expexted output: (memberk 3 '(1 4 (3 1) 2)) = '((3 1) 2)
Actual output from the code above: '((3 1) . #f)
So how I see this you would like the top level cons that has the key found somewhere in car. I'm thinking something like:
(define (memberk needle lst)
(define (found? haystack)
(or (equal? needle haystack)
(and (pair? haystack)
(or (found? (car haystack))
(found? (cdr haystack))))))
(let loop ((lst lst))
(cond ((null? lst) #f)
((found? (car lst)) lst)
(else (loop (cdr lst))))))
(memberk '(a) '(a b (b (a) c) c d)) ; ==> ((b (a) c) c d)
Something like this?
It is a bit unclear what you want - since there is only one test case.
(define (memberk thing lis)
(cond
[(null? lis)
#f]
[(and (cons? (car lis)) (memberk thing (car lis)))
=> (λ (found) (cons found (cdr lis)))]
[(equal? (car lis) thing)
lis]
[else
(memberk thing (cdr lis))]))

need to combine results of two functions in Scheme with a driver

I have a Scheme assignment in which a user is to input a list of numbers, and the output should be the max value and min value from the list. The assignment says we can have two separate functions, and combine the result with a driver, but I don't know how to do this. Here is what I have so far:
(define (findmin l) (if (null? (cdr l)) (car l)
(if (< (car l) (findmin (cdr l)))(car l)
(findmin (cdr l)))))
(define (findmax l) (if (null? (cdr l)) (car l)
(if (> (car l) (findmax (cdr l)))(car l)
(findmax (cdr l)))))
I can't seem to get around having to input a list for findmin, and another list for findmax. The user should only have to input one list.
driver:
(define (min-and-max l) (list (findmin l) (findmax l)))

Resources