scheme: rotation function is not working - rotation

(define rotate
(lambda (ls)
(define subrotate
(lambda (head tail res)
(if (null? tail)
res
(subrotate (append head (list (car tail)))
(cdr tail)
(cons (append tail head) res)))))
(if (null? ls)
ls
(subrotate '() ls '())))) (rotate '(a b c d e))
I want to make function that if list (a b c d e), print ((a b c d e) (b c d e a) (c d e a b) (d e a b c) (e a b c d)) but when I execute that function, it prints (e a b c d) (d e a b c) .......
I think this function will activate like
tail | head | res
'() | (a b c d e) | '()
a | (b c d e) | (b c d e a)
(a b) | (c d e) | (c d e a b)
(a b c) | (d e) | (d e a b c)
(a b c d) | (e) | (e a b c d)
(a b c d e) | () | (a b c d e)
and I expect it only print (a b c d e) but result is not. How can I modify this and why it prints every rotation?

The problem is in the way you're adding new elements to the output list. This should fix it:
(define rotate
(lambda (ls)
(define subrotate
(lambda (head tail res)
(if (null? tail)
res
(subrotate (append head (list (car tail)))
(cdr tail)
(append res (list (append tail head))))))) ; modified
(if (null? ls)
ls
(subrotate '() ls '()))))
Alternatively, you could simply reverse the output list:
(define rotate
(lambda (ls)
(define subrotate
(lambda (head tail res)
(if (null? tail)
(reverse res) ; modified
(subrotate (append head (list (car tail)))
(cdr tail)
(cons (append tail head) res)))))
(if (null? ls)
ls
(subrotate '() ls '()))))
And just for fun, here's a more compact implementation of the same algorithm, this time using a named let:
(define (rotate ls)
(let subrotate ((head '()) (tail ls) (res '()))
(if (null? tail)
(reverse res)
(subrotate (append head (list (car tail)))
(cdr tail)
(cons (append tail head) res)))))

Related

reverse a general list using scheme

I am trying to reverse a general list using Scheme. How can I reverse a complex list?
I can make a single list like (A B C D) works using my function, but for some complex list inside another list like (F ((E D) C B) A), the result is just (A ((E D) C B) F). How can I improve it?
(define (reverse lst)
(if (null? lst)
lst
(append (reverse (cdr lst)) (list (car lst)))))
Any comments will be much appreciated!
Here is another way that uses a default parameter (r null) instead of the expensive append operation -
(define (reverse-rec a (r null))
(if (null? a)
r
(reverse-rec (cdr a)
(cons (if (list? (car a))
(reverse-rec (car a))
(car a))
r))))
(reverse-rec '(F ((E D) C B) A))
; '(A (B C (D E)) F)
Using a higher-order procedure foldl allows us to encode the same thing without the extra parameter -
(define (reverse-rec a)
(foldl (lambda (x r)
(cons (if (list? x) (reverse-rec x) x)
r))
null
a))
(reverse-rec '(F ((E D) C B) A))
; '(A (B C (D E)) F)
There are several ways of obtaining the expected result. One is to call reverse recursively also on the car of the list that we are reversing, of course taking care of the cases in which we must terminate the recursion:
(define (reverse x)
(cond ((null? x) '())
((not (list? x)) x)
(else (append (reverse (cdr x)) (list (reverse (car x)))))))
(reverse '(F ((E D) C B) A))
'(A (B C (D E)) F)
(A ((E D) C B) F) is the correct result, if your goal is to reverse the input list. There were three elements in the input list, and now the same three elements are present, in reverse order. Since it is correct, I don't suggest you improve its behavior!
If you have some other goal in mind, some sort of deep reversal, you would do well to specify more clearly what result you want, and perhaps a solution will be easier to find then.

Apply procedure on previous result

Given a list of lists as an input, I want to execute a procedure such that the final result would be:
(define (thing . lists) ; list of lists (l1 l2 ... lN)
;returns ...f(f(f(l1 l2) l3) lN)...
)
So for example:
(thing '(a b) '(c d) '(e f))
...would result in f(f((a b) (c d)) (e f))
I am fighting with folding, lambda, apply and map, but I can't figure out right way.
Assuming that the input has at least two lists and that f was previously defined:
(define (thing . lists)
(foldr (lambda (lst acc)
(f acc lst))
(f (car lists) (cadr lists))
(cddr lists)))
For example:
(define f append)
(thing '(a b) '(c d) '(e f))
=> '(a b c d e f)

Recursion on deep list scheme

I have created a function that takes a list as input and returns either a list or a atom. I want to apply this function to a deep list, starting with the inner lists, then finish once the function has been run on the outer list.
Can somebody give me some direction on this?
A sample input would be (a b (c (d e))) z) the function should compute on (d e) first with a result of say f. then the function should compute on (c f) with a result of say g then similarly on (a b g z) to produce an output of h.
An example function could be:
(define sum
(lambda (l)
(if (not (pair? l))
0
(+ (car l) (sum (cdr l))))))
Where input would be (1 2 (3 4) 5) > 15
Assuming your example transformation, expressed as a Scheme procedure:
(define (transform lst)
(case lst
(((d e)) 'f)
(((c f)) 'g)
(((a b g z)) 'h)
(else (error (~a "wot? " lst)))))
then what you are looking for seems to be
(define (f lst)
(transform
(map (lambda (e)
(if (list? e) (f e) e))
lst)))
Testing:
> (f '(a b (c (d e)) z))
'h
Here is an example:
(define product
(lambda (l)
(cond
[(number? l) l]
[(pair? l) (* (product (car l)) (product (cdr l)))]
[else 1])))
> (product '(1 2 (3 4) 5))
120

Getting every nth atom using scheme does not pick up the last atom

The program is suppose to pick out every third atom in a list.
Notice that the last atom 'p' should be picked up, but its not.
Any suggestions as to why the last atom is not being selected.
(define (every3rd lst)
(if (or (null? lst)
(null? (cdr lst)))
'()
(cons (car lst)
(every3rd (cdr(cdr(cdr lst)))))))
(every3rd '(a b c d e f g h i j k l m n o p))
Value 1: (a d g j m)
Thanks
You're missing a couple of base cases:
(define (every3rd lst)
(cond ((or (null? lst) (null? (cdr lst))) lst)
((null? (cdr (cdr lst))) (list (car lst)))
(else (cons (car lst)
(every3rd (cdr (cdr (cdr lst))))))))
See how the following cases should be handled:
(every3rd '())
=> '()
(every3rd '(a))
=> '(a)
(every3rd '(a b))
=> '(a)
(every3rd '(a b c))
=> '(a)
(every3rd '(a b c d))
=> '(a d)
(every3rd '(a b c d e f g h i j k l m n o p))
=> '(a d g j m p)
Fixing your code (covering the base cases)
It's worth noting that Scheme defines a number of c[ad]+r functions, so you can use (cdddr list) instead of (cdr (cdr (cdr list))):
(cdddr '(a b c d e f g h i))
;=> (d e f g h i)
Your code, as others have already pointed out, has the problem that it doesn't consider all of the base cases. As I see it, you have two base cases, and the second has two sub-cases:
if the list is empty, there are no elements to take at all, so you can only return the empty list.
if the list is non-empty, then there's at least one element to take, and you need to take it. However, when you recurse, there are two possibilies:
there are enough elements (three or more) and you can take the cdddr of the list; or
there are not enough elements, and the element that you took should be the last.
If you assume that <???> can somehow handle both of the subcases, then you can have this general structure:
(define (every3rd list)
(if (null? list)
'()
(cons (car list) <???>)))
Since you already know how to handle the empty list case, I think that a useful approach here is to blur the distinction between the two subcases, and simply say: "recurse on x where x is the cdddr of the list if it has one, and the empty list if it doesn't." It's easy enough to write a function maybe-cdddr that returns "the cdddr of a list if it has one, and the empty list if it doesn't":
(define (maybe-cdddr list)
(if (or (null? list)
(null? (cdr list))
(null? (cddr list)))
'()
(cdddr list)))
> (maybe-cdddr '(a b c d))
(d)
> (maybe-cdddr '(a b c))
()
> (maybe-cdddr '(a b))
()
> (maybe-cdddr '(a))
()
> (maybe-cdddr '())
()
Now you can combine these to get:
(define (every3rd list)
(if (null? list)
'()
(cons (car list) (every3rd (maybe-cdddr list)))))
> (every3rd '(a b c d e f g h i j k l m n o p))
(a d g j m)
A more modular approach
It's often easier to solve the more general problem first. In this case, that's taking each nth element from a list:
(define (take-each-nth list n)
;; Iterate down the list, accumulating elements
;; anytime that i=0. In general, each
;; step decrements i by 1, but when i=0, i
;; is reset to n-1.
(let recur ((list list) (i 0))
(cond ((null? list) '())
((zero? i) (cons (car list) (recur (cdr list) (- n 1))))
(else (recur (cdr list) (- i 1))))))
> (take-each-nth '(a b c d e f g h i j k l m n o p) 2)
(a c e g i k m o)
> (take-each-nth '(a b c d e f g h i j k l m n o p) 5)
(a f k p)
Once you've done that, it's easy to define the more particular case:
(define (every3rd list)
(take-each-nth list 3))
> (every3rd '(a b c d e f g h i j k l m n o p))
(a d g j m)
This has the advantage that you can now more easily improve the general case and maintain the same interface every3rd without having to make any changes. For instance, the implementation of take-each-nth uses some stack space in the recursive, but non-tail call in the second case. By using an accumulator, we can built the result list in reverse order, and return it when we reach the end of the list:
(define (take-each-nth list n)
;; This loop is like the one above, but uses an accumulator
;; to make all the recursive calls in tail position. When
;; i=0, a new element is added to results, and i is reset to
;; n-1. If i≠0, then i is decremented and nothing is added
;; to the results. When the list is finally empty, the
;; results are returned in reverse order.
(let recur ((list list) (i 0) (results '()))
(cond ((null? list) (reverse results))
((zero? i) (recur (cdr list) (- n 1) (cons (car list) results)))
(else (recur (cdr list) (- i 1) results)))))
It is because (null? '()) is true. you can debug what's happening with following code
(define (every3rd lst)
(if (begin
(display lst)
(newline)
(or (null? lst)
(null? (cdr lst))))
'()
(cons (car lst)
(every3rd (cdr(cdr(cdr lst)))))))
(every3rd '(a b c d e f g h i j k l m n o p))
(newline)
(display (cdr '(p)))
(newline)
(display (null? '()))
(newline)
(display (null? (cdr '(p))))
(newline)
this gives following result.
(a b c d e f g h i j k l m n o p)
(d e f g h i j k l m n o p)
(g h i j k l m n o p)
(j k l m n o p)
(m n o p)
(p)
()
#t
#t

Get last n elements in a list in DrRacket, without list-ref

I know how to get the first n elements in a list,
(define (countup n ls)
(cond
[(zero? n) '()]
[else (cons (first ls) (countup (sub1 n) (rest ls)))]))
but how can I do something like this for the last n elements in a list (without using list-ref)?
If I call (countup 3 '(a b c d e)), I get (list a b c). I need to be able to enter (counter 3 '(a b c d e)) and get (list c d e).
I need error messages in case the number n given is bigger than the list's length.
Just use the built-in take-right procedure, it does exactly what you need:
(take-right '(a b c d e) 3)
=> '(c d e)
Or you can implement it from scratch, using primitive procedures:
(define (counter n lst)
(define (move n lst)
(if (zero? n)
lst
(move (sub1 n) (rest lst))))
(define (trim-left lst rst)
(if (empty? rst)
lst
(trim-left (rest lst) (rest rst))))
(trim-left lst (move n lst)))
It also works as expected:
(counter 3 '(a b c d e))
=> '(c d e)
I guess I would use a local fn to chop of items from the left and then return the remaining items. The following also returns '() if asked to return a Negative number of items. You may want to treat this as an error as well. #f signals an error in your input ie trying to take more items than the list contains
(define (counter n loN)
(define (acc loN c)
(cond [(null? loN) '()]
[(> c 0) (acc (cdr loN) (sub1 c))]
[else loN]))
;in
(let ((c (- (length loN) n)))
(cond ; [(>= 0 n) #f]
[(positive? c) (acc loN c)]
[else #f])))
(check-equal? (counter 3 '(a b c d e)) '(c d e))
(check-equal? (counter 6 '(a b c d e)) #f)
(check-equal? (counter -3 '(a b c d e)) '())
(check-equal? (counter 0 '(a b c d e)) '())

Resources