How do I write a division function in scheme - scheme

This is my first week using scheme, and I'm stuck on a simple problem. I want to write a function that does simple integer division. This is what I've written and I'm getting a bad syntax error. Any help on how to fix this and make the code work?
(define divisible-by
(lambda (a b)
(if (= a b)
(display #f))
)
(if (= (remainder a b) 0)
(display #t)
(else
(display #f))
)
)

Here is an answer that you won't be able to submit but which shows you how you might approach this.
I assume you are not allowed to simply use division, so one way to divide n by d, assuming n is a natural number and d is a non-zero natural number, is to repeatedly subtract d from n while incrementing a result, r, until you get a number which is less than d, which is the remainder. Here is that:
(define (div/rem n d)
;; Return the quotient and remainder of n by d
;;
;; You should perhas check they are naturals here, and that d is non-zero
;;
(define (div/rem-loop m r)
(if (< m d)
(values r m)
(div/rem-loop (- m d) (+ r 1))))
(div/rem-loop n 0))
There are more concise ways of writing this (named let is the obvious one).

Related

SICP Exercise 2.5 - How to represent negative numbers?

I'm currently reading the SICP, and working on Exercise 2.5 :
Exercise 2.5. Show that we can represent pairs of nonnegative integers using only numbers and arithmetic operations if we represent the pair a and b as the integer that is the product 2a3b. Give the corresponding definitions of the procedures cons, car, and cdr.
And I've found a code:
(define (my-cons a b)
(* (expt 2 a) (expt 3 b)))
(define (my-car x)
(define (car-iter x count)
(if (= 0 (remainder x 2))
(car-iter (/ x 2) (+ 1 count))
count))
(car-iter x 0))
(define (my-cdr x)
(define (cdr-iter x count)
(if (= 0 (remainder x 3))
(cdr-iter (/ x 3) (+ 1 count))
count))
(cdr-iter x 0))
My question is : What if the requirement of "Nonnegative integers" needs to be changed to "Accept both negative and nonnegative integers" ?
Example :
> (define x (my-cons 2 -5))
> (my-car x)
2
> (my-cdr x)
-5
How to modify the code? I can't figure it out.
Thank you. May you have a great day.
As amalloy said in a comment this is really a maths problem. This encoding works because of the fundamental theorem of arithmetic, which is that any positive natural number has a unique prime factorisation: every positive natural can be represented uniquely as the product of a number of primes raised to powers, where in particular 1 is the product of no primes.
So you could encode the sign of the integers using one or more additional prime factors (you only need one, in fact, as you can for instance write the thing as 2^a3^b5^s where s is an integer in [0,3] which encodes the signs of both elements).
An alternative way is simply to use the existing representation but to map the integers to the naturals. This is nice because it's a practical demonstration that there are no more integers than naturals. Such a map might be:
if i >= 0 then 2i.
otherswise -2i - 1.
It's easy to see that this is a one-to-one correspondence, and also that 0 maps to 0 (which makes 0 a nice value for nil).
Here are these maps, written (sorry) in typed Racket as I'm trying to work out if I can use it.
(define (Z->N (i : Integer)) : Natural
;; map an integer to a natural
(if (>= i 0)
(* i 2)
(- (* (- i) 2) 1)))
(define (N->Z (n : Natural)) : Integer
;; map the naturals into the integers
(let-values ([(q r) (quotient/remainder n 2)])
(if (zero? r)
q
(- (- q) 1))))
Now there is another problem with the implementation you have: it will happily handle numbers which are not of the form 2^a3^b, for instance anything which has other prime factors. The way to deal with that is to check that numbers are of that form when extracting the powers: in practice this means checking the number is of the form 2^a*3^b*1.
So the code below does this, as well as encoding integers as above. This again is in typed Racket (sorry, again), and it also makes use of multiple values and probably some other things which only exist in Racket.
(define (defactor (n : Natural) (p : Natural)) : (Values Natural Natural)
;; Given n and a factor p, return m where p does not divide m,
;; and j, the number of factors of p removed (so n = m*p^j)
(let df-loop ([m : Natural n]
[j : Natural 0])
(let-values ([(q r) (quotient/remainder m p)])
(if (zero? r)
(df-loop q (+ j 1))
(values m j)))))
(define (kar&kdr (k : Positive-Integer)) : (Values Integer Integer)
;; Given something which should be a kons, return its kar & kdr.
;; If it is not a kons signal an error
(let*-values ([(k2 encoded-kar) (defactor k 2)]
[(k23 encoded-kdr) (defactor k2 3)])
(unless (= k23 1)
(error 'kar&kdr "not a cons"))
(values (N->Z encoded-kar) (N->Z encoded-kdr))))
(define (kons (the-kar : Integer) (the-kdr : Integer)) : Positive-Integer
(* (expt 2 (Z->N the-kar))
(expt 3 (Z->N the-kdr))))
(define (kar (the-kons : Positive-Integer)) : Integer
(let-values ([(the-kar the-kdr) (kar&kdr the-kons)])
the-kar))
(define (kdr (the-kons : Positive-Integer)) : Integer
(let-values ([(the-kar the-kdr) (kar&kdr the-kons)])
the-kdr))
We can go a little further and define a representation of the empty list, which will be 0 and a way of making lists:
;;; since 2^a3^b is never zero, 0 is a good candidate for the empty
;;; list: 'kill' is a pun on 'nil'.
;;;
(define kill : Zero 0)
;;; And now we can write some predicates and a version of list.
;;; (kist 1 2 3) takes a very, very long time.
;;;
(define (kill? (x : Natural)) : Boolean
(zero? x))
(define (kons? (x : Natural)) : Boolean
(not (kill? x)))
(define (kist . (l : Integer *)) : Natural
(let kist/spread ((lt l))
(if (null? lt)
kill
(kons (first lt) (kist/spread (rest lt))))))
And now
> (define d (kons 123 -456))
> d
- : Integer [more precisely: Nonnegative-Integer]
51385665200410193914365219310409629004573395973849642473134969706165383608831740620563388986738635202925909198851954060195023302783671526117732269828652603388431987979605951272414330987611274752111186624164906143978901704325355283206259678088536996807776750955110998323447711166379786727609752016045005681785186498933895920793982869940159108073471074955985333560653268614500306816876936016985137986665262182684386364851688838680773491949813254691225004097103180392486216812280763694296818736638062547181764608
> (kar d)
- : Integer
123
> (kdr d)
- : Integer
-456
> (kdr (+ d 1))
kar&kdr: not a cons [,bt for context]
If you try to compute, say (kist 1 2 3) it will take a very, very long time.

I'm trying to figure out how to incorporate 3 variables into my tail recursion code for racket

Write a tail recursive function called popadd that models a population with P people at time t = 0 and adds d people per year.
(define (popadd t P)
(if (= t 0)
P
(+(popadd( - t 1) P)d))
)
but, of course, I get the error that d hasn't been defined yet, which is true. I tried adding it as an input, but as a return I get the number inserted for D.
You can simply pass along another parameter to the recursion:
(define (popadd t P d)
(if (= t 0)
P
(+ d (popadd (- t 1) P d))))
Or you can define the value, to avoid passing it around - assuming it doesn't need to change:
(define d 100)
(define (popadd t P)
(if (= t 0)
P
(+ d (popadd (- t 1) P))))
Notice that you could do the same with P, if it's ok. It really depends on what's the expected contract for the procedure.
Note that neither your code nor the code in the other answer is tail-recursive: in a recursive call like (+ (f ...)), f is not in tail position. To make the code tail-recursive you need the result of the recursive call be the result of the overall call (so in the above example, + is in tail position). To do this you need an auxiliary function. Here is a way of doing it which relies only on local define:
(define (popadd t P d)
(define (popadd-loop tau pop)
(if (zero? tau)
pop
(popadd-loop (- tau 1) (+ pop d))))
(popadd-loop t P))
Here is essentially the same thing using named-let, which is nicer:
(define (popadd t P d)
(let popadd-loop ([tau t] [pop P])
(if (zero? tau)
pop
(popadd-loop (- tau 1) (+ pop d)))))
Finally note that this problem has a closed-form solution:
(define (popadd t P d)
(+ P (* t d)))
I really wish that people trying to teach programming knew enough maths to not set problems which have trivial closed-form answers, as doing so encourages people to write inefficient (in the complexity-class sense) code. Obviously this is not your fault: it's your teacher's.

Scheme Procedure that takes an argument and outputs a value

I am trying to write a procedure called bal-val that has to take in a single argument and output the value of the ball. The values for the balls are R = 5, G=4, B = 3, and W = 1.
The code I have is:
(define (bal-val n)
(if (= n R))
(= n 5)
(if (= n G))
(= n 4)
(if (= n B))
(= n 3)
(if (= n W))
(= n 1))
First of all (= n 5) applys the function = to the constant 5 and the variable n. Therefore it returns a Boolean value, it does not set n to be 5.
The main issue though is wrong use of Predicates:
= predicate is used to check whether two numbers are equal. If you supply anything else (but a number) it will raise an error.
The eq? predicate is used to check whether its two parameters respresent the same object in memory.
The equal? predicate tests for same value in primitive types and can also check two lists, vectors, etc.
This is what you are trying to do:
(define (bal-val n)
(if (equal? n 'R)
5
(if (equal? n 'G)
4
(if (equal? n 'B)
3
(if (equal? n 'W)
1
(error 'not_found))))))
You might want to use cond in this case as it resembles switch behavior more naturally. Done like so:
(define (bal-val-cond n)
(cond ((equal? n 'R) 5)
((equal? n 'G) 4)
((equal? n 'B) 3)
((equal? n 'W) 1)
(else (error 'not_found))))
coding 101 - ALWAYS indent your code correctly, it makes it understandable and with time errors will stand out and you will be able to spot them much quicker.

Error : for: undefined (Scheme)

I have to make a function in Scheme (R5RS) that works as follow :
(power-close-to b n)
And it has to return a integer that I call "e" that is :
b^e > n
With b, e and n integers.
So if we do :
(power-close-to 2 10)
It has to return 4, because 4 is the first integer for which b^e > n
I've made this function in an iterative way but I have to make it in an recursive form.
So this is my code:
(define e 0)
(define (power-close-to b n)
(for ((e (< (expt b e) n))
(+ e 1))
e))
But when I try it, Scheme gives following error : "for: undefined;"
So it seems my Scheme don't know the procedure "for", but I saw it in multiple Scheme codes on the internet, so I don't understand why in my case he says he don't know "for".
Thanks for your help!
EDIT : I tried making it recursive, this is how i did it, but i think it still is iterative, and i really don't have any idea how i could make it recursive.
(define e 0)
(define (power-close-to b n)
(if (< (expt b e) n)
(and (set! e (+ e 1)) (power-close-to b n))
e))
I also tried this, but when i try it, it never prints anything and never ends (but this is recursive (i think))
(define e 0)
(define (power-close-to b n)
(if (< (expt b e) n)
(* b (power-close-to b n))
e))
When someone asks you to transform a recursive procedure in Scheme into an iterative one, it generally means that you have to use tail recursion, not that you should use the looping constructs of the language.
Notice that not all Scheme interpreters provide a for loop (most will provide a do loop, but I don't think that's the point of the exercise). The error you're reporting means that your interpreter doesn't have a for construct, so it's quite possible that you're expected to rewrite the procedure in a tail recursive fashion. I'll give you an example of what I mean, this is a recursive factorial:
(define (fac n)
(if (zero? n)
1
(* n (fac (sub1 n)))))
(fac 10)
=> 3628800
Now the same procedure can be written in such a way that it generates an iterative process (even though syntactically, it still uses recursion):
(define (fac n acc) ; now the result is stored in the accumulator parameter
(if (zero? n) ; when recursion ends
acc ; return accumulator
(fac (sub1 n) (* n acc)))) ; else update accumulator in each iteration
(fac 10 1) ; initialize the accumulator in the right value
=> 3628800
What's the point, you ask? that the second version of the procedure is written in tail-recursive form (notice that there's nothing left to do after the recursive call ends), so a compiler trick called tail call optimization kicks in and the procedure runs in constant stack space, just as efficient as a loop in other non-functional languages - making recursive calls very cheap. Now try to write your power-close-to implementation so it uses a tail call.
What comes closest (and handiest) to the traditional loop is the named let (search for "named let" here). That would look like this:
(define (power-close-to b n)
(let loop ((e 0))
(if (<= (expt b e) n)
(loop (+ e 1))
e)))
(display (power-close-to 2 10))
The loop variable is defined at the let level, so it is local to the loop (at not global as in your example). Other than that the code looks pretty similar to yours.
A named let creates an inner function, so you could also express it as follows:
(define (power-close-to b n)
(define (loop e)
(if (<= (expt b e) n)
(loop (+ e 1))
e))
(loop 0))
Unfortunately, R5RS does not support default values for arguments, but if you want to avoid the inner function you could go for:
(define (power-close-to b n e)
(if (<= (expt b e) n)
(power-close-to b n (+ e 1))
e))
but then you'd have to call it with an additional 0 like
(power-close-to 2 10 0)

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