Nested functions in scheme - scheme

I'm new to scheme language and trying to execute this code that calculating the n'th Fibonacci series using an internal function.
for some reason it doesn't work for me and i would like to get some help.
Thank you.
(define fibo (lambda (n)
(define (helperFunction n n1 a_n)
(begin
(display a_n)
(newline)
(if (> n 1)
(helperFunction (- n 1) (+ n1 a_n) n1))))
(helperFunction n 1 1)))

First off, why do you use the long version in fibo and the short version in helperFunction? eg.
(define long-version (lambda (arg) arg))
(define (short-version arg) arg)
These are the same. Books often use the long version to point out that functions are values and the names are bindings just as with variables, but its practical to use the short version when you already have started with it.
a begin that wraps the contents of a function is unnecessary since all functions have explicit begin.
An if where you only have a test and a then clause will return a implementation chosen value when the test is false. I tend to use the symbol undefined to not get any surprises on what the undefined value is.
You need to indent your code properly. I use DrRacket and press CTRL+I. With these I get your code like this:
(define (fibo n)
(define (helperFunction n n1 a_n)
(display a_n)
(newline)
(if (> n 1)
(helperFunction (- n 1) (+ n1 a_n) n1)
'undefined))
(helperFunction n 1 1))
So lets try this:
(fibo 1) ; ==> undefined
That makes sense from looking at the code. It's hardly correct but it does what it has been instructed to do. What if it was 2?
(fibo 2) ; ==
(helperFunction 1 2 1) ==> undefined
I think your problem is that instead of undefined you should have n1 as the result.
(define (fibo n)
(define (helperFunction n n1 a_n)
(display a_n)
(newline)
(if (> n 1)
(helperFunction (- n 1) (+ n1 a_n) n1)
n1))
(helperFunction n 1 1))
A note on the function. A standard fibonacci goes like 0,1,1,2,3,5 and the function is usually zero indexed such that:
(fib 0) ; ==> 0
(fib 1) ; ==> 1
(fib 10) ; ==> 55

Related

In Scheme, how can I display something multiply times?

`(display-n "*" 4)`
****
This code should give 4 stars. How can I display this?
Also, this code should fit in this:
Finally figured out the entire good code. Thanks for all the hints and feedback!
(define (display-n k n)
(if (> n 0)
(do ((x 0 (+ x 1)))
((= x n))
(display k))))
(define (parasol n)
(define (triangle i)
(if (< i n)
(begin
(display-n " "(- n i 1))
(display-n "*" (+ (* 2 i) 1))
(newline)
(triangle (+ i 1)))))
(define (stick i)
(if (< i 3)
(begin
(display-n " " (- n 1))
(display "*") (newline)
(stick (+ i 1)))))
(triangle 0)
(stick 0))
(parasol 5)
Phrased differently, your question is:
How can I repeat an operation `n` times?
The solution is to use a loop. In Scheme you can choose between a "named let" or a "do loop".
See detailed explanation here:
What does the "do" control construct do in Scheme?
(define (display-n n k)
(if (> k 0)
(do ((x 0 (+ x 1)))
((= x k))
(display n))))
Found it. I'll put this here if an unfortunate soul is looking for the same thing.
For this specific case, since you're only outputting a single character long string, you can just make a string of n copies of that character and print it instead of using an explicit loop:
(define (display-n k n)
(display (make-string n (string-ref k 0))))
(display-n "*" 4)
or if passing a character instead of a string:
(define (display-n k n)
(display (make-string n k)))
(display-n #\* 4)
While knowing how to repeat an arbitrary task a given number of times is generally useful and probably a big point of the exercise, being able to find simpler approachs for special cases is also a good skill to have.

Scheme if expression returns '#<void>' if the body contains an expression

So I am currently reading SICP and I am stuck at exercise 1.22, since I do not understand why my program isn't working the way I intend it to work. Here is the Code
#lang sicp
; the given function to time the search for a prime
(define (timed-prime-test n)
(newline)
(display n)
(start-prime-test n (runtime)))
(define (start-prime-test n start-time)
(if (prime? n)
(report-prime (- (runtime) start-time))))
(define (report-prime elapsed-time)
(display " *** ")
(display elapsed-time))
; finds the smallest natural number that can divide n without any remainder
(define (smallest-divisor n)
(define (square x)
(* x x))
(define (divides? a b)
(= (remainder a b) 0))
(define (find-divisor n test-divisor)
(cond ((> (square test-divisor) n) n)
((divides? n test-divisor) test-divisor)
(else (find-divisor n (+ test-divisor 1)))))
(find-divisor n 2))
; returns true if the given number n is prime
(define (prime? n)
(= n (smallest-divisor n)))
; start searching at start and found keeps track of the amount of
; primes found, if it equals 3 return found
(define (search-for-primes start found)
(if (= found 3)
found ; after finding 3 primes above start return
((timed-prime-test start) ; if not continue search with start + 1
(search-for-primes (+ start 1) (if (not (prime? start))
found
(+ found 1))))))
(search-for-primes 1000 0)
The problem is that when I run this program it works fine until it finds a prime number. The interpreter that I use is racket and the program terminates with:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
3
1019 *** 0
If I understand the interpreter correctly than it should evaluate this expression according to the applicative-order evaluation principle right? So why is it passing the if expression as a procedure to my search-for-primes procedure? What am I missing here?
The problem is in search-for-primes, if you have more than one expression in one of the legs of an if, then you need to put them inside a begin block - surrounding it with () won't work. This should fix the problem:
(define (search-for-primes start found)
(if (= found 3)
found
(begin ; add this!
(timed-prime-test start)
(search-for-primes (+ start 1) (if (not (prime? start))
found
(+ found 1))))))

how to append elements in a list in 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)

EOPL/Racket/Scheme Random Number List between two numbers

This the task:
Write a function (random-number-list n lim) which returns a list of n random integers in the range 0 through lim-1
This is my Code: (I am using #lang EOPL in DrRacket)
(define (random-number-list n lim)
(letrec ((maker
(lambda (n lim result)
(let loop ((g lim) (result '()))
(if (= g 0)
result
(loop (- lim 1) (cons (random lim) result)))))))
(maker n lim '())))
This should be what it produce:
(random-number-list 10 20) => (1 11 4 18 3 12 17 17 8 4)
When I run the code I receive an error dealing with "(random lim)." Something to with random. Would anyone know the reason? Also, am I on the correct track?
The main problem with your code is in this line:
(loop (- lim 1) (cons (random lim) result))
You're decrementing lim but testing against g, which remains unchanged, leading to an infinite loop. Also, g was incorrectly initialized in this line:
((g lim) (result '()))
This should fix the problems:
(define (random-number-list n lim)
(letrec ((maker
(lambda (n lim result)
(let loop ((g n) (result '()))
(if (= g 0)
result
(loop (- g 1) (cons (random lim) result)))))))
(maker n lim '())))
Given that you're using Racket, know that a simpler solution is possible:
(define (random-number-list n lim)
(build-list n (lambda (x) (random lim))))
Either way, it works as expected:
(random-number-list 10 20)
=> '(13 7 5 9 3 12 7 8 0 4)
The main reason you get an error is that the langiage #!eopl doesn have a procedure named random. If you se the eported symbols of eopl it simply doesn't exist. It does exist in #!racket though.
As Oscar pointed out there were some logical errors that leads to infinite loops. An honest mistake, but I also notice you use g instead of n in your inner loop. It's very common to use the original name instead of the chosen local variable so a common way to not do that mistake is to shadow the original variable.
There is also only need for one local procedure. Here are my corrections with either keeping the named let or the letrec:
#!racket
;; with letrec
(define (random-number-list n lim)
(letrec ((maker
(lambda (n result)
(if (zero? n)
result
(maker (- n 1)
(cons (random lim) result))))))
(maker n '())))
;; with named let
(define (random-number-list2 n lim)
(let maker ((n n) (result '()))
(if (zero? n)
result
(maker (- n 1)
(cons (random lim) result)))))
I left lim out since it never changes and i used the same name maker to illustrate it's exactly the same that happens in these two, only the syntax are different. Many implementations actually rewrites the named let to something very similar to the letrec version.
An alternative:
(define (random-number-list n lim)
(build-list n (λ (x) (random lim)))
Here build-list builds a list of n elements.
Each element is the result of calling (λ (x) (random lim))
which ignores x and returns a random number between 0 and lim-1.

weirdness in scheme

I was trying to implement Fermat's primality test in Scheme.
I wrote a procedure fermat2(initially called fermat1) which returns true
when a^p-1 congruent 1(mod p) (please read it correctly guys!!)
a
every prime p number should satisfy the procedure (And hence Fermat's little theorem .. )
for any a
But when I tried to count the number of times this procedure yields true for a fixed number of trials ... ( using countt procedure, described in code) I got shocking results ans
So I changed the procedure slightly (I don't see any logical change .. may be I'm blind) and named it fermat1(replacing older fermat1 , now old fermat1 ->fermat2) and it worked .. the prime numbers passed the test all the times ...
why on earth the procedure fermat2 called less number of times ... what is actually wrong??
if it is wrong why don't I get error ... instead that computation is skipped!!(I think so!)
all you have to do , to understand what I'm trying to tell is
(countt fermat2 19 100)
(countt fermat1 19 100)
and see for yourself.
Code:
;;Guys this is really weird
;;I might not be able to explain this
;;just try out
;;(countt fermat2 19 100)
;;(countt fermat1 19 100)
;;compare both values ...
;;did you get any error using countt with fermat2,if yes please specify why u got error
;;if it was because of reminder procedure .. please tell your scheme version
;;created on 6 mar 2011 by fedvasu
;;using mit-scheme 9.0 (compiled from source/microcode)
;; i cant use a quote it mis idents (unfriendly stack overflow!)
;;fermat-test based on fermat(s) little theorem a^p-1 congruent to 1 (mod p) p is prime
;;see MIT-SICP,or Algorithms by Vazirani or anyother number theory book
;;this is the correct logic of fermat-test (the way it handles 0)
(define (fermat1 n)
(define (tryout a x)
;; (display "I've been called\n")
(= (remainder (fast-exp a (- x 1)) x) 1))
;;this exercises the algorithm
;;1+ to avoid 0
(define temp (random n))
(if (= temp 0)
(tryout (1+ temp) n)
(tryout temp n)))
;;old fermat-test
;;which is wrong
;;it doesnt produce any error!!
;;the inner procedure is called only selective times.. i dont know when exactly
;;uncomment the display line to see how many times tryout is called (using countt)
;;i didnt put any condition when it should be called
;;rather it should be every time fermat2 is called
;;how is it so??(is it to avoid error?)
(define (fermat2 n)
(define (tryout a x)
;; (display "I've been called\n")
(= (remainder (fast-exp a (- x 1)) x) 1))
;;this exercises the algorithm
;;1+ to avoid 0
(tryout (1+ (random n)) n))
;;this is the dependency procedure for fermat1 and fermat2
;;this procedure calculates base^exp (exp=nexp bcoz exp is a keyword,a primitive)
;;And it is correct :)
(define (fast-exp base nexp)
;;this is iterative procedure where a*b^n = base^exp is constant always
;;A bit tricky though
(define (logexp a b n)
(cond ((= n 0) a);;only at the last stage a*b^n is not same as base^exp
((even? n) (logexp a (square b) (/ n 2)))
(else (logexp (* a b) b (- n 1)))))
(logexp 1 base nexp))
;;utility procedure which takes a procedure and its argument and an extra
;; argument times which tells number of times to call
;;returns the number of times result of applying proc on input num yielded true
;;counting the number times it yielded true
;;procedure yields true for fixed input,
;;by calling it fixed times)
;;uncommenting display line will help
(define (countt proc num times)
(define (pcount p n t c)
(cond ((= t 0)c)
((p n );; (display "I'm passed by fermat1\n")
(pcount p n (- t 1) (+ c 1)));;increasing the count
(else c)))
(pcount proc num times 0))
I had real pain .. figuring out what it actually does .. please follow the code and tell why this dicrepieancies?
Even (countt fermat2 19 100) called twice returns different results.
Let's fix your fermat2 since it's shorter. Definition is: "If n is a prime number and a is any positive integer less than n, then a raised to the nth power is congruent to a modulo n.". That means f(a, n) = a^n mod n == a mod n. Your code tells f(a, n) = a^(n-1) mod n == 1 which is different. If we rewrite this according to definition:
(define (fermat2 n)
(define (tryout a x)
(= (remainder (fast-exp a x) x)
(remainder a x)))
(tryout (1+ (random n)) n))
This is not correct yet. (1+ (random n)) returns numbers from 1 to n inclusive, while we need [1..n):
(define (fermat2 n)
(define (tryout a x)
(= (remainder (fast-exp a x) x)
(remainder a x)))
(tryout (+ 1 (random (- n 1))) n))
This is correct version but we can improve it's readability. Since you're using tryout only in scope of fermat2 there is no need in parameter x to pass n - latter is already bound in scope of tryout, so final version is
(define (fermat n)
(define (tryout a)
(= (remainder (fast-exp a n) n)
(remainder a n)))
(tryout (+ 1 (random (- n 1)))))
Update:
I said that formula used in fermat2 is incorrect. This is wrong because if a*k = b*k (mod n) then a = b (mod n). Error as Vasu pointed was in generating random number for test.

Resources