create a list in c lisp recursively - list

I am trying to create a list in lisp that starts at n and ends at 2.
(setq liste ())
(defun makeList (n)
(if (> n 2)
(setq liste (append (makeList (- n 1)) liste)
(setq liste (append liste 2))))
This doesn't seem to work. Anybody help?

setq only changes a variable. You need to define it first. If you rely on a global variable then the second time around your result will have the elements of the previous run. It's very smelly!
;; With recursion
(defun my-make-list (start)
(if (< start 2)
'()
(cons start (my-make-list (1- start)))))
;; with tail recursion
(defun my-make-list (start)
(labels ((helper (cur acc)
(if (> cur start)
acc
(helper (1+ cur) (cons cur acc)))))
(helper 2 '())))
;; With loop
(defun my-make-list (start)
(loop :for n :from start :downto 2
:collect n))
The last one is best since CL doesn't guarantee tail call optimization. Notice that I do the tail recursive one in reverse since all lists are made from end to beginning.

Related

Scheme: A iterator function return only one value at the time

Lets say, i have a function range that returned a list of number by step, I have implemented that and it worked fine. Now, I need to write a iterator function on top of that, so if I run the iterator function on the list, it will return the first element of the list overtime.
(define next '(1 2 3 4))
(next) => 1
(next) => 2
(next) => 3
(next) => 4
(next) => '()
My question is I don't know what type of syntax of scheme can achieve that since every time we call the function next, the will should get refreshed. But i need to implement the next function so that if i call next on the list the second time, the list do not get refreshed, so it will get the second item of the list
Is there any specific method I need to know about to achieve this or do i need to modify my range function to do that.
My iteration function looks like this:
(define (iterator L)
(let ((start (car L))
(step (car (cdr L)))
(end (car (cdr (cdr L))))
)
(lambda ()
(if (> start end)
'()
(set! start
(+ start step)
)
)
)
)
)
My next definitiin
(define next (iterator '(0 2 7)))
Error message i have is: Error: execute: unbound symbol: "iterator" [].
For starters, there's a bug in your range code:
(define (range L)
(let ((start (car L))
(step (car (cdr L)))
(end (car (cdr (cdr L)))))
(if (> start end)
'() ; fix this line
(cons start (range (list (+ start step) step end))))))
Now, to create an iterator we need to introduce state into our procedure, to remember where we're in each step of the iteration. Also notice that there are two separate concepts here: the iterator and the procedure to advance it, we can use currying to return the next procedure. Here's my proposal:
(define (iter lst)
(let ((pos lst)) ; store current position
(lambda () ; return the `next` procedure
(if (null? pos) ; are we done?
'() ; then exit
(let ((cur (car pos))) ; current element
(set! pos (cdr pos)) ; advance & update state
cur))))) ; return current
Use it like this:
(define next (iter (range '(1 1 3))))
(next)
=> 1
(next)
=> 2
(next)
=> 3
(next)
=> '()

Racket exchanging first and third elements of a list in a function?

Suppose, I got a list(s) in Racket of:
`(1 2 3)
`(1 2 3 4)
`((1 2) (3) (4)))
Then when I exchange it (first and third element), it will look like:
`(3 2 1)
`(3 2 1 4)
`((4) (3) (1 2))
Please note: I may only use things such as cons, first, and rest for this.
Here's my current try:
(define new-list
(lambda(list)
(first (rest (rest list))))) ; Get third element.
I cannot replicate the results above. I would like to be shown how it's done.
Just play with it a little:
> '(one)
'(one)
> '(one two three)
'(one two three)
> (first '(one two three four))
'one
> (rest '(one two three four))
'(two three four)
> (define foo (lambda (lst)
(cons (first lst) (rest lst))))
> (foo '(one two three four))
'(one two three four)
> (define bar (lambda (lst)
(cons (first (rest lst))
(cons (first lst) (rest lst)))))
> (bar '(one two three four))
'(two one two three four)
Now you have everything to complete the process.
To write your procedure, we want to take an input list xs, and construct a new list like
(cons (third-element xs)
(cons (second-element xs)
(cons (first-element xs)
(everything-except-the-first-three-elements xs)))
In racket you have car and cdr, but you also have cadr, caddr, cddddr and everything in betweeen.
To get an intuition for them, a reads the head, d reads the tail, so
car gets the head (the first element in a list)
cdr gets the tail (everything except the first element in a list)
cadr gets the head of the tail (the second element in a list)
cddr gets the tail of the tail (everything except the first and second elements in a list)
caddr gets the head of the tail of the tail (the third element in a list)
and so on ...
We can write this easily using our car and cdr helpers
(define (swap xs)
(cons (caddr xs) ; cons the third element ...
(cons (cadr xs) ; onto the second element ...
(cons (car xs) ; onto the first element ...
(cdddr xs))))) ; onto the tail of the third element
(swap '(1 2 3)) ; '(3 2 1)
(swap '(1 2 3 4)) ; '(3 2 1 4)
(swap '((1 2) (3) (4))) ; '((4) (3) (1 2))
(define nth
;; Return nth element of list
(lambda (lst n)
(cond ((null? lst) 'nil)
((zero? n) (car lst))
(else (nth (cdr lst) (- n 1))))))
(define slice
;; Return lst sliced like python
(lambda (lst a b acc)
(cond ((null? lst) (reverse acc))
((< b a) (reverse acc))
((zero? b) (reverse acc))
((zero? a) (slice (cdr lst) 0 (- b 1) (cons (car lst) acc)))
(else (slice (cdr lst) (- a 1) (- b 1) acc)))))
(define swap
;; Return nth and mth element swapped list
(lambda (lst n m)
`(,#(slice lst 0 n '())
,(nth lst m)
,#(slice lst (+ n 1) m '())
,(nth lst n)
,#(slice lst (+ m 1) (length lst) '()))))
This swaps any two given positions m and n and returns the resulting list.
(swap your-list 0 2) ; returns your-list 1st and 3rd elements swapped

racket: counting number of siblings

Having nested lists as the input, I'm trying to find how to output the number of 'siblings' an element has. In terms of trees, how many other leaf nodes belong to the same parent/root node.
My code is giving the wrong outputs (it's a really bad code) and I'm not sure how to entirely approach the question
(define (siblings lst n)
(cond
[(empty? lst) false]
[(member? n lst) (sub1 (length lst))]
[else (siblings (rest lst) n)]))
sample outcomes: if given (list (list 2 1) 3 (list 4)) and 3, produce 0
(list (list 1 2 3) (list (list 4 5 6 ))) and 5 -> 2
Your code has to do two separate things:
Find the branch that contains n
Count the number of siblings in that branch, accounting for the possibility of other branches starting there.
Finding the branch that contains n, assuming that n can only appear once:
(define (find-branch root n)
(cond ((empty? root) empty)
((memq n root)
root)
((list? (first root))
(let ((subresult (find-branch (first root) n)))
(if (not (empty? subresult))
subresult
(find-branch (rest root) n))))
(else (find-branch (rest root) n))))
Since you're using "Beginning Student," that takes all the tools out of your toolbox. Fortunately, it still has number?, so if it's safe to assume that anything that isn't a number in this assignment is a list, you can define list? like this:
(define (list? n) (not (number? n)))
Given your example tree as input, it would return:
(4 5 6)
The above example unnecessarily uses memq repeatedly on the rest of the
input list as a result of using recursion to iterate over the same list.
Here's a more efficient version of the above, but you can't implement it in Beginning Student:
(define (find-branch root n)
(cond ((empty? root) false)
((memq n root) root)
(else (foldl (λ (a b)
(if (empty? a) b a))
empty
(map (λ (sublist)
(find-branch sublist n))
(filter list? root))))))
You pass the result of that to a function to count the siblings. I previously provided a version that would work in the real Racket, but not the Beginning Student version used by teachers:
(define (count-siblings root mem)
(count (λ (sib)
(and (not (eq? sib mem))
(not (list? sib)))) root))
Here's a version that's compatible with Beginning Student:
(define (count-siblings lst n counter)
(cond
[(empty? lst) counter]
[(and (not (list? (first lst)))
(not (eq? n (first lst))))
(count-siblings (rest lst) n (add1 counter))]
[else (count-siblings (rest lst) n counter)]))
Finally, put the two together:
(define (find/count-siblings root n)
(count-siblings (find-branch root n) n 0))

Depth of list in scheme

I'm trying to write a program in scheme that will find the maximum depth of a list. My code so far is:
(define (depth l)
(define (helper l count)
( cond
((null? l) count)
((not(list? (car l))) (helper (cdr l) count))
(else (helper (car l) (+ count 1)) )
)
)
(helper l 1)
)
It works for lists of this type (depth '(1 2 3 (2))) -> 2, but obviously not for list of the type (depth '( (2) ((3))) -> 3. The problem is that when I first encounter a list, I automatically jump to it increment the count and call it recursively again, ignoring the other elements of the list. I want to fix this problem and I thought of adding another variable temp which to hold the current count for each element in the list and check if it is bigger than count and if it is true I set! count to temp, but again I have a problem with the recursion. My other idea was to use another list in which to append count on every step and find the maximum value in that list, but I couldn't realize that too. Any ideas how to do this problem?
Here's an implementation using map:
(define (max-depth l)
(define (helper depth el)
(cond
[(null? el) (add1 depth)]
[(list? el)
(apply max
(map (curry helper (add1 depth))
el))]
[else depth]))
(helper 0 l))
While I think this implementation is fairly elegant, it admittedly is not tail-recursive.
Here is a slightly more complex, breadth-first tail-recursive implementation:
(define (max-depth l)
(define (helper depth els)
(define remaining (filter list? els))
(if (zero? (length remaining))
depth
(helper (add1 depth) (apply append remaining))))
(helper 1 l))

Having a hard time with delete-ing every nth element in Lisp?

Trying to learn lisp, want to delete every nth. I only managed to delete the first (nth) element
(defun delete-nth (n list)
(if (zerop n)
(cdr list)
(let ((cons (nthcdr (1- n) list)))
(if cons
(setf (cdr cons) (cddr cons))
cons))))
I'd like to delete the next nth and so on
Also I tried this:
(defun remove-nth (list n)
(remove-if (constantly t) list :start n :end (+ 1 n)))
No idea how to start again
What I was thinking was concatenating, but I have no idea of how to keep track of my position.
Counting from 1 (changing to 0 is trivial):
(defun remove-every-nth (n list)
(loop for element in list
for index from 1
unless (zerop (rem index n))
collect element))
Also: Please indent your code correctly.
An alternative way to do the same thing:
(defun remove-all-nth (list period)
(remove-if
(let ((iterator 0))
(lambda (x)
(declare (ignore x))
(= 0 (mod (incf iterator) period)))) list))
(remove-all-nth '(1 2 3 4 5 6 7 8 9 0) 3)
; (1 2 4 5 7 8 0)
Perhaps a more academic recursive solution here:
(defun delete-nth (n list)
(labels ((rec (i list)
(cond ((null list) nil)
((= i 1) (rec n (cdr list)))
(t (cons (car list) (rec (1- i) (cdr list)))))))
(rec n list)))
But in real life I'd use the loop option above.