Avoid double recursion - recursion

(DEFUN F(L)
(COND
((NULL L) NIL)
((LISTP (CAR L))
(APPEND (F (CAR L))
(F (CDR L))
(CAR (F (CAR L)))))
(T (LIST (CAR L)))
))
This function returns a dotted pair(if the first element is a sublist) with the first element of the sublist as the right part and on the left part are the element on the right and the second element of the list(if not sublist).Now,how can I rewrite this without using the double recursion of (F (CAR L)) and without using SET,SETQ,SETF?

Use LET to bind a local variable to the repeated recursive call.
(DEFUN F(L)
(COND
((NULL L) NIL)
((LISTP (CAR L))
(LET ((FCAR (F CAR L)))
(APPEND FCAR
(F (CDR L))
(CAR FCAR))))
(T (LIST (CAR L)))
))

Related

Implementing last-non-zero without continuations

last-non-zero takes a list of numbers and return the last cdr whose car is 0.
So, I can implement it using continuations, but how do I do this with natural recursion.
(define last-non-zero
(lambda (ls)
(let/cc return
(letrec
((lnz
(lambda (ls)
(cond
((null? ls) '())
((zero? (car ls)) ;; jump out when we get to last 0.
(return (lnz (cdr ls))))
(else
(cons (car ls) (lnz (cdr ls))))))))
(lnz ls)))))
Here's an obvious version which is not tail-recursive:
(define (last-non-zero l)
;; Return the last cdr of l which does not contain zero
;; or #f if there is none
(cond
((null? l)
#f)
((zero? (car l))
(let ((lnzc (last-non-zero (cdr l))))
;; This is (or lnzc (cdr l)) but that makes me feel bad
(if lnzc
lnzc
(cdr l))))
(else
(last-non-zero (cdr l)))))
Here is that version turned into a tail-recursive equivalent with also the zero test moved around a bit.
(define (last-non-zero l)
(let lnzl ([lt l]
[r #f])
(if (null? lt)
r
(lnzl (cdr lt) (if (zero? (car lt)) (cdr lt) r)))))
It's much clearer in this last version that the list is traversed exactly once.
Please indicate if I have correctly understood the problem:
#lang scheme
; returns cdr after last zero in lst
(define (last-non-zero lst)
; a helper function with 'saved' holding progress
(define (lnz-iter lst saved)
(if (null? lst)
saved
(if (zero? (car lst))
(lnz-iter (cdr lst) (cdr lst))
(lnz-iter (cdr lst) saved))))
(lnz-iter lst '()))
(last-non-zero '(1 2 3 0 7 9)) ; result (7 9)
Racket's takef-right can do it:
> (takef-right '(1 2 0 3 4 0 5 6 7) (lambda (n) (not (zero? n))))
'(5 6 7)
But assuming you have an assignment where you're supposed to write the logic yourself instead of just using a built in function, one easy if not very efficient approach is to reverse the list, build a new list out of everything up to the first zero, and return that. Something like:
(define (last-non-zero ls)
(let loop ([res '()]
[ls (reverse ls)])
(if (or (null? ls) (zero? (car ls)))
res
(loop (cons (car ls) res) (cdr ls)))))
Using your implementation where you return the argument in the event there are no zero you can just have a variable to keep the value you think has no zero values until you hit it and then update both:
(define (last-non-zero lst)
(let loop ((lst lst) (result lst))
(cond ((null? lst) result)
((zero? (car lst)) (loop (cdr lst) (cdr lst)))
(else (loop (cdr lst) result)))))
(last-non-zero '()) ; ==> ()
(last-non-zero '(2 3)) ; ==> (2 3)
(last-non-zero '(2 3 0)) ; ==> ()
(last-non-zero '(2 3 0 1 2)) ; ==> (1 2)
(define last-non-zero
(lambda (l)
((lambda (s) (s s l (lambda (x) x)))
(lambda (s l* ret)
(if (null? l*)
(ret '())
(let ((a (car l*))
(r (cdr l*)))
(if (zero? a)
(s s r (lambda (x) x))
(s s r
(lambda (r)
(ret (cons a r)))))))))))
Also possible, to use foldr:
(define (last-non-zero l)
(reverse (foldl (lambda (e res) (if (zero? e) '() (cons e res))) 0 l)))
Or use recursion:
(define (last-non-zero l (res '()))
(cond ((empty? l) res)
((zero? (car l)) (last-non-zero (cdr l) (cdr l)))
(else (last-non-zero (cdr l) res))))

How to remove a list of length 1 from a nested list in lisp?

I have a nested list (1 (4 (5) 3) 9 10) and I want to delete the lists of length 1 so the result would be (1 (4 3) 9 10).
This is what I have tried so far, which does not remove (5) and returns the original list.
(defun remove (l)
(cond
((null l) nil)
((and (listp (car l)) (= (length l) 1)) (remove (cdr l)))
((atom (car l)) (cons (car l) (remove (cdr l))))
(T (cons (remove (car l)) (remove (cdr l))))
))
Two things: first, remove is a predefined function in package CL, so I strongly advice to use a different name, let's say my-remove.
Second, you are testing the length of l instead of the sublist (car l), which is what you want to eliminate.
The correct form would be:
(defun my-remove (l)
(cond
((null l) nil)
((and (listp (car l)) (= (length (car l)) 1)) (my-remove (cdr l)))
((atom (car l)) (cons (car l) (my-remove (cdr l))))
(T (cons (my-remove (car l)) (my-remove (cdr l))))
))
Tail call recursive version. Plus: Without the test (atom (car l)) to be permissive for non-list and non-atom components in the list. (e.g. vectors or other objects as element of the list - they are treated like atoms.
(defun my-remove (l &optional (acc '()))
(cond ((null l) (nreverse acc))
((listp (car l)) (if (= 1 (length (car l))) ;; list objects
(my-remove (cdr l) acc) ;; - of length 1
(my-remove (cdr l) (cons (my-remove (car l)) acc)))) ;; - longer
(t (my-remove (cdr l) (cons (car l) acc))))) ;; non-list objects

Racket define list

I have to solve nest task using language Racket. By given list I have to create new list holding only elements that division by 10 has no leftover.
My code so far:
(define (brel x sp)
(cond ((null? sp) 0)
(( = (remainder (car sp) 10) 0) (car sp))
(else (brel x (cdr sp)))))
(define (spbr L)
(define (f l1)
(if (null? l1) '()
(cons (brel (car l1) L) (f (cdr l1)))))
(f L))
(spbr (list 50 5 3))
Give code currently count every repeats of elements in first list and add them in new one. What must I change to make it works?
You don't need a helper procedure, just build a new list with only the items that meet the condition:
(define (spbr L)
(cond ((null? L) '())
((= (remainder (car L) 10) 0)
(cons (car L) (spbr (cdr L))))
(else
(spbr (cdr L)))))
Using the filter procedure would be more idiomatic:
(define (spbr L)
(filter (lambda (e) (zero? (remainder e 10)))
L))
Either way, it works as expected:
(spbr '(50 5 3 70))
=> '(50 70)

Vector multiply function in scheme, manipulating initial recursive parameter

I've been working on a vector multiply function in scheme and have found myself in rut. I dont want to use any looping and I dont want to use any scheme built in functions other than the ones I've already included. I've created a helper function called rotate and dotproduct. I can get the correct values if I do this in racket (vectormult '(1 2 -1) (rotate '((0 2 3) (1 2 0) (1 0 3)))). How can I rotate the initial parameter without re-rotating after every recursive call? NOTE: I dont want to introduce additional paramaters. If my logic/approach to this is all wrong please help me get on the right track.
Code
(define dotproduct
(lambda (l1 l2)
(if (or (null? l1) (null? l2))
0
(+ (* (car l1) (car l2)) (dotproduct (cdr l1) (cdr l2))))))
(define getFirsts
(lambda (l)
(cond
((null? l) `())
(else (cons (first* l) (getFirsts (cdr l)))))))
(define removeFirsts
(lambda (l)
(cond
((null? l) `())
((null? (car l)) `())
(else (cons (cdr (car l)) (removeFirsts (cdr l)))))))
(define rotate
(lambda (l)
(cond
((null? l) `())
((null? (first* l)) `())
(else (cons (getFirsts l) (rotate (removeFirsts l)))))))
(define vectormult
(lambda (l1 l2)
(cond
((null? l2) `())
(else (cons (dotproduct l1 (car l2)) (vectormult l1 (cdr l2)))))))
If I understand the question, you could rename your current vectormult to, say, rotatedvectormult (and change its recursive call accordingly), and then have vectormult just rotate the parameter before calling rotatedvectormult. This way, rotatedvectormult would know the parameter was already rotated, but vectormult could still take an unrotated vector.
I ended up ditching the rotate function in favor of adding 2 functions getFirsts and removeFirsts.
Code
(define getFirsts
(lambda (l)
(cond
((null? l) `())
(else (cons (first* l) (getFirsts (cdr l)))))))
(define removeFirsts
(lambda (l)
(cond
((null? l) `())
((null? (car l)) `())
(else (cons (cdr (car l)) (removeFirsts (cdr l)))))))
;(define rotate
; (lambda (l)
; (cond
; ((null? l) `())
; ((null? (first* l)) `())
; (else (cons (getFirsts l) (rotate (removeFirsts l)))))))
(define vectormult
(lambda (l1 l2)
(cond
((null? (first* l2)) `())
(else (cons (dotproduct l1 (getFirsts l2)) (vectormult l1 (removeFirsts l2)))))))

what am i doing wrong in this code? im trying to check if all the elements in a list are the same, and no matter the test cases i get a #f

Create the function AllEqual?(L) which will be given a list of (at least 2) elements and will return #t if all of them are the same, otherwise #f
(define (allequal? l)
(if (< (length l) 2)
#t
(equal? (car l) (allequal? (cdr l)))))
(equal? (car l) (allequal? (cdr l)))
tests if (car l) is equal? to (allequal? ...). Since allequal? returns a boolean (#t or #f), you test if (car l) is #t or #f, which is not what you want.
You need to compare the first two elements, if available, and then recurse on the cdr of your list:
(define (allequal? l)
(if (< (length l) 2)
#t
(and (equal? (car l) (cadr l))
(allequal? (cdr l)))))
or, easier,
(define (allequal? l)
(or (< (length l) 2)
(and (equal? (car l) (cadr l))
(allequal? (cdr l)))))
or even
(define (allequal? l)
(or (null? l)
(null? (cdr l))
(and (equal? (car l) (cadr l))
(allequal? (cdr l)))))

Resources