how to append elements in a list in Scheme - scheme

I have made a program that returns the number of a fibonacci series by using tail recursion, and I would like to add its results to a list. I have done the following:
(define listAux '())
(define (fibTail n1 n2 c)
(if (= c 0)
(appendList -1)
(begin
(appendList n2)
(fibT (+ n1 n2) n1 (- c 1))
)))
(define (appendList n)
(if (= n -1)
listAux
(append (list n) listAux)))
(define (fib n)
(fibTail 1 0 n))
I would like that appendList returns a list with the elements of the fibonacci series, when I call it like (fib 8) for example.
Any help?
Thanks

When programming in Lisp, we avoid using append for building lists - it's very inefficient because to insert a single element at the end, we have to traverse the whole list... and then again, and again. It's better to build the list in reverse order using cons and invert it at the end. Also, the ideal way of writing a tail recursion is to accumulate the results in a parameter, not in an externally defined variable (which anyway won't work, unless you set! its value somewhere). This is what I mean:
(define (fib n)
(fibTail 1 0 n '()))
(define (fibTail n1 n2 c lst)
(if (< c 0)
(reverse lst)
(fibTail (+ n1 n2) n1 (- c 1) (cons n2 lst))))
For example:
(fib 10)
=> '(0 1 1 2 3 5 8 13 21 34 55)

Related

Shifting k times to the left

Hi I am trying to implement a program in scheme shifting a list k times to the left.
For example:
(shift-k-left ’(1 2 3) 2)
’(3 1 2)
I have managed to implement a code that do shift left once here:
(define shift-left
(lambda (ls)
(if (null? ls)
'()
(append (cdr ls)
(cons (car ls)
'())))))
I want to use shift left as a function on shift-k-left.
Here is a solution using circular-list from srfi/1.
(require srfi/1)
(define (shift xs k)
(define n (length xs))
(take (drop (apply circular-list xs) k) n))
Using your shift-left to shift k times:
If k is 0: do nothing
If k is not 0: shift k-1 times, and then shift-left the result.
That is,
(define (shift-left-k ls k)
(if (= k 0)
ls
(shift-left (shift-left-k ls (- k 1)))))
You may want to adjust to do something sensible for negative k.
The idea is to count down n while consing the cars of r to p and the cdrs to r then the base case becomes append r to the reverse of p. If we run into a null? r we reverse p and continue this wraps the rotation:
(define (shift-k-left l n)
; assume that n >= 0
(let loop ((n n) (p '()) (r l))
(if (= n 0)
(append r (reverse p))
(if (null? r)
(loop n '() (reverse p))
(loop (- n 1) (cons (car r) p) (cdr r))))))
Here is something similar:
(define (addn value n)
(let loop ((value value) (n n))
(if (zero? n)
value
(loop (add1 value) (- n 1)))))
(addn 5 3)
; ==> 8
Now you could make an abstraction:
(define (repeat proc)
(lambda (v n)
...))
(define addn (repeat add1))
(addn 5 3)
; ==> 8
(define shift-k-left (repeat shift-left))
(shift-k-left ’(1 2 3) 2)
; ==> (3 1 2)
Needless to say repeat looks a lot like add1 does.
NB: The naming is off. Your implementation is more "rotate" than "shift".
shift-left is actually more like cdr than your implemenation.

Scheme - speed up a heavily recursive function

I must write a Scheme predicate that computes the function f(N -> N) defined as :
if n < 4 :f(n)= (n^2) + 5
if n ≥ 4 :f(n) = [f(n−1) + f(n−2)] * f(n−4)
I wrote a simple predicate that works :
(define functionfNaive
(lambda (n)
(if (< n 4) (+ (* n n) 5)
(* (+ (functionfNaive (- n 1)) (functionfNaive (- n 2)))
(functionfNaive (- n 4))))))
Now, I try a method with an accumulator but it doesn't work...
My code :
(define functionf
(lambda(n)
(functionfAux n 5 9 14)))
(define functionfAux
(lambda (n n1 n2 n4)
(cond
[(< n 4) (+ (* n n) 5)]
[(= n 4) (* n1 (+ n2 n4))]
[else (functionfAux (- n 1) n2 n4 (* n1 (+ n2 n4)))])))
As requested, here's a memoized version of your code that performs better than the naïve version:
(define functionf
(let ((cache (make-hash)))
(lambda (n)
(hash-ref!
cache
n
(thunk
(if (< n 4)
(+ (* n n) 5)
(* (+ (functionf (- n 1)) (functionf (- n 2))) (functionf (- n 4)))))))))
BTW... computing the result for large values of n is very quick, but printing takes a lot of time. To measure the time, use something like
(time (functionf 50) 'done)
AND here's a generic memoize procedure, should you need it:
(define (memoize fn)
(let ((cache (make-hash)))
(λ arg (hash-ref! cache arg (thunk (apply fn arg))))))
which in your case could be used like
(define functionf
(memoize
(lambda (n)
(if (< n 4)
(+ (* n n) 5)
(* (+ (functionf (- n 1)) (functionf (- n 2))) (functionf (- n 4)))))))
First, that's not a predicate. A Predicate is a function which returns a Boolean value.
To calculate the nth result, start with the first four and count up, maintaining the last four known elements. Stop when n is reached:
(define (step a b c d n)
(list b c d (* (+ c d) a)) (+ n 1)))
etc. Simple. The first call will be (step 5 6 9 14 3).
The depth of the recursion tree may be the biggest question, so may be use the iteration which means use some variables to memory the intermediate processes.
#lang racket
(define (functionf n)
(define (iter now n1 n2 n3 n4 back)
(if (= n now)
back
(iter (+ now 1) back n1 n2 n3 (* n3 (+ back n1)))))
(if (< n 4)
(+ 5 (* n n))
(iter 4 14 9 6 5 125)))
(functionf 5)
in this way, the depth of the stack only be 1 and the code is speeded up.

How to decrement a value in Scheme?

I have a procedure that can find the n smallest primes larger than from
(define (primes_range from to n)
(for ([i (in-range from to)])
(if (> n 0)
(cond ((prime? i) (display i)
(- n 1)))
false)))
I add a parameter n to the procedure primes_range and decrement it during the execution only if a prime was found.
But n not changed. How to fix that?
The idiomatic Scheme way to write this function is to use recursion:
(define (primes-range from to n)
(cond ((>= from to) '())
((<= n 0) '())
((prime? from) (cons from (primes-range (+ from 1) to (- n 1))))
(else (primes-range (+ from 1) to n))))
You can easily spell this out in English:
Base cases:
A prime range where the from is equal or greater to to is empty.
A prime range where n is 0 or less is empty.
Recursive cases:
If from is a prime, then the prime range is from, prepended to the result of calling primes-range starting from (+ from 1) and with (- n 1) elements.
Otherwise, the result is calling primes-range starting from (+ from 1) (still with n elements).

Do two things in Racket "for loop"

I'm running a for loop in racket, for each object in my list, I want to execute two things: if the item satisfies the condition, (1) append it to my new list and (2) then print the list. But I'm not sure how to do this in Racket.
This is my divisor function: in the if statement, I check if the number in the range can divide N. If so, I append the item into my new list L. After all the loops are done, I print L. But for some unknown reason, the function returns L still as an empty list, so I would like to see what the for loop does in each loop. But obviously racket doesn't seem to take two actions in one "for loop". So How should I do this?
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)])
(if (equal? (modulo N i) 0)
(append L (list i))
L)
)
write L)
Thanks a lot in advance!
Note: This answer builds on the answer from #uselpa, which I upvoted.
The for forms have an optional #:when clause. Using for/fold:
#lang racket
(define (divisors N)
(reverse (for/fold ([xs '()])
([n (in-range 1 N)]
#:when (zero? (modulo N n)))
(displayln n)
(cons n xs))))
(require rackunit)
(check-equal? (divisors 100)
'(1 2 4 5 10 20 25 50))
I realize your core question was about how to display each intermediate list. However, if you didn't need to do that, it would be even simpler to use for/list:
(define (divisors N)
(for/list ([n (in-range 1 N)]
#:when (zero? (modulo N n)))
n))
In other words a traditional Scheme (filter __ (map __)) or filter-map can also be expressed in Racket as for/list using a #:when clause.
There are many ways to express this. I think what all our answers have in common is that you probably want to avoid using for and set! to build the result list. Doing so isn't idiomatic Scheme or Racket.
It's possible to create the list as you intend, as long as you set! the value returned by append (remember: append does not modify the list in-place, it creates a new list that must be stored somewhere) and actually call write at the end:
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)]) ; generate a stream in the range 1..N
(when (zero? (modulo N i)) ; use `when` if there's no `else` part, and `zero?`
; instead of `(equal? x 0)`
(set! L (append L (list i))) ; `set!` for updating the result
(write L) ; call `write` like this
(newline)))) ; insert new line
… But that's not the idiomatic way to do things in Scheme in general and Racket in particular:
We avoid mutation operations like set! as much as possible
It's a bad idea to write inside a loop, you'll get a lot of text printed in the console
It's not recommended to append elements at the end of a list, that'll take quadratic time. We prefer to use cons to add new elements at the head of a list, and if necessary reverse the list at the end
With all of the above considerations in place, this is how we'd implement a more idiomatic solution in Racket - using stream-filter, without printing and without using for loops:
(define (divisor N)
(stream->list ; convert stream into a list
(stream-filter ; filter values
(lambda (i) (zero? (modulo N i))) ; that meet a given condition
(in-range 1 N)))) ; generate a stream in the range 1..N
Yet another option (similar to #uselpa's answer), this time using for/fold for iteration and for accumulating the value - again, without printing:
(define (divisor N)
(reverse ; reverse the result at the end
(for/fold ([acc '()]) ; `for/fold` to traverse input and build output in `acc`
([i (in-range 1 N)]) ; a stream in the range 1..N
(if (zero? (modulo N i)) ; if the condition holds
(cons i acc) ; add element at the head of accumulator
acc)))) ; otherwise leave accumulator alone
Anyway, if printing all the steps in-between is necessary, this is one way to do it - but less efficient than the previous versions:
(define (divisor N)
(reverse
(for/fold ([acc '()])
([i (in-range 1 N)])
(if (zero? (modulo N i))
(let ([ans (cons i acc)])
; inefficient, but prints results in ascending order
; also, `(displayln x)` is shorter than `(write x) (newline)`
(displayln (reverse ans))
ans)
acc))))
#sepp2k has answered your question why your result is always null.
In Racket, a more idiomatic way would be to use for/fold:
(define (divisor N)
(for/fold ((res null)) ((i (in-range 1 N)))
(if (zero? (modulo N i))
(let ((newres (append res (list i))))
(displayln newres)
newres)
res)))
Testing:
> (divisor 100)
(1)
(1 2)
(1 2 4)
(1 2 4 5)
(1 2 4 5 10)
(1 2 4 5 10 20)
(1 2 4 5 10 20 25)
(1 2 4 5 10 20 25 50)
'(1 2 4 5 10 20 25 50)
Since append is not really performant, you usually use cons instead, and end up with a list you need to reverse:
(define (divisor N)
(reverse
(for/fold ((res null)) ((i (in-range 1 N)))
(if (zero? (modulo N i))
(let ((newres (cons i res)))
(displayln newres)
newres)
res))))
> (divisor 100)
(1)
(2 1)
(4 2 1)
(5 4 2 1)
(10 5 4 2 1)
(20 10 5 4 2 1)
(25 20 10 5 4 2 1)
(50 25 20 10 5 4 2 1)
'(1 2 4 5 10 20 25 50)
To do multiple things in a for-loop in Racket, you just write them after each other. So to display L after each iteration, you'd do this:
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)])
(if (equal? (modulo N i) 0)
(append L (list i))
L)
(write L))
L)
Note that you need parentheses to call a function, so it's (write L) - not write L. I also replaced your write L outside of the for-loop with just L because you (presumably) want to return L from the function at the end - not print it (and since you didn't have parentheses around it, that's what it was doing anyway).
What this will show you is that the value of L is () all the time. The reason for that is that you never change L. What append does is to return a new list - it does not affect the value of any its arguments. So using it without using its return value does not do anything useful.
If you wanted to make your for-loop work, you'd need to use set! to actually change the value of L. However it would be much more idiomatic to avoid mutation and instead solve this using filter or recursion.
'Named let', a general method, can be used here:
(define (divisors N)
(let loop ((n 1) ; start with 1
(ol '())) ; initial outlist is empty;
(if (< n N)
(if(= 0 (modulo N n))
(loop (add1 n) (cons n ol)) ; add n to list
(loop (add1 n) ol) ; next loop without adding n
)
(reverse ol))))
Reverse before output since items have been added to the head of list (with cons).

Printing First two numbers in scheme

I'm trying to print the first 2 numbers in a list coded in Scheme. I'm having a bit of trouble doing this. I get an error when I run the procedure. Any suggestions on how I can get this to work
(define (print-two-nums n nums)
( list-ref nums(+ (cdr nums) n)))
( print-two-nums 2'(5 5 4 4))
It looks like you were wavering between the ideas of "print two numbers" and "print n numbers." If you really want just the two first numbers of a list, you can write:
(define (print-two-nums nums)
(print (list (car nums) (cadr nums))))
But for the more general first n numbers, you can use:
(define (print-n-nums n nums)
(print (take nums n)))
To print the first n numbers, you could use this simple procedure
(define (print-n-nums L n) (cond
((or (= 0 n) (null? L)) '())
(else (cons (car L) (print-n-nums (cdr L) (- n 1))))))
(print-n-nums (list 1 2 3) 2)
;Output: (1 2)
You could further abstract the cons operation and define print-n-nums as a higher order procedure to carry out the desired operation. For example, if we wanted to add the first n numbers of a list, we could define the following procedure. Here OPERATION is a function that we pass to the list-operator function. Thus, here we want to perform the + operation. In the case above, we want to perform the cons operation. The initial parameter is just how we want to handle the edge case.
(define (list-operator L n OPERATION initial) (cond
((or (= 0 n) (null? L)) initial)
(else (OPERATION (car L) (list-operator (cdr L) (- n 1) OPERATION initial)))))
(list-operator (list 1 2 3) 2 + 0)
;Output: 3
Now, if you wanted the product of the first 2 numbers, you would just do
(list-operator (list 1 2 3) 2 * 1)

Resources