I have created two different methods, using SCHEME, to count how many primes exist between 1 and n. I can't understand why the second method doesn't work.
The one that works -
define (count-primes t)
(cond((= t 1) 0)
((prime? t) (+ 1 (count-primes (- t 1))))
(else (count-primes(- t 1)))
)
The one that doesn't work -
(define x 0)
(define (count-primes t)
(cond((= t 1) x)
((prime? t) (+ x 1) (count-primes (- t 1)))
(else (count-primes(- t 1)))
)
)
The problem is with (+ x 1) expression. If you want to increment some variable in Scheme, you have to assign new value to it's name:
(set! x (+ x 1))
It's not enough to simply add some values like you did. It just adds them and then ignores the result because you did not specify what to do with it.
You can also redefine this function to take one more, optional argument and pass x this way, avoiding defining and mutating x separately. Something like:
(define (count-primes t . x)
(cond ((= t 1) (car x))
((prime? t) (+ x 1) (count-primes (- t 1) (+ (car x) 1)))
(else (count-primes (- t 1) (car x)))))
Note you have to take car of x, because x is actually a list of all optional arguments, but we use only first one, so - car.
Related
I'm starting to coding in Scheme and I wan't to know if a number is "abundante". A number x is "abundante" if the sum of its dividers is greater than the double of x.
So this is my code:
#lang scheme
(define (abundante x)
(cond
((= x 0) #f)
((= x 1) #f)
((> (apply +(divisores x)) (doble x)) #t)
(else #f)
)
)
;aux functions
(define (doble x) (* x 2))
(define (divisores x)
(cond
((= x 1) '(1))
(else (cons 1 (divisores-aux x 2)))
)
)
(define (divisores-aux x y)
(cond
((= x y) '(x))
((integer? (/ x y))(cons y (divisores-aux x (+ y 1))))
(else (divisores-aux x (+ y 1)))
)
)
As you can see, I have 3 auxiliary functions:
1) Doble x: Return the double of x
2) Divisores x: Return the dividers of x
2.1) Divisores-aux x y: Check if x/y is a integer number, then goes for y+1
But I got the problem when Divisores-aux reach x = y. I want to return x because x its a divider of itself but DrRacket prints the follow error:
+: contract violation
expected: number?
given: y
argument position: 6th
other arguments...:
And indicates me that the error was produced on apply +(divisores x)
If I return null or '() everything goes fine, but obviously I don't get the correct result.
Thanks in advance
There's a bug in the base case of divisores-aux, in here:
'(x)
The above expression will return a list with the symbol x as its single member (to understand why, read about quoting in the docs). What you meant to say was this, that creates a list with the value of the x variable:
(list x)
Also, it's better to use remainder to test if a number is divided by another. This should fix the issues:
(define (divisores-aux x y)
(cond
((= x y) (list x))
((zero? (remainder x y)) (cons y (divisores-aux x (+ y 1))))
(else (divisores-aux x (+ y 1)))))
Now abundante works as expected:
(abundante 42)
=> #t
(abundante 45)
=> #f
I'm new to CHICKEN and Scheme. In my quest to understanding tail recursion, I wrote:
(define (recsum x) (recsum-tail x 0))
(define (recsum-tail x accum)
(if (= x 0)
accum
(recsum-tail (- x 1) (+ x accum))))
This does what I expect it to. However, this seems a little repetitive; having an optional argument should make this neater. So I tried:
(define (recsum x . y)
(let ((accum (car y)))
(if (= x 0)
accum
(recsum (- x 1) (+ x accum)))))
However, in CHICKEN (and maybe in other scheme implementations), car cannot be used against ():
Error: (car) bad argument type: ()
Is there another way to implement optional function arguments, specifically in CHICKEN 5?
I think you're looking for a named let, not for optional procedure arguments. It's a simple way to define a helper procedure with (possibly) extra parameters that you can initialize as required:
(define (recsum x)
(let recsum-tail ((x x) (accum 0))
(if (= x 0)
accum
(recsum-tail (- x 1) (+ x accum)))))
Of course, we can also implement it with varargs - but I don't think this looks as elegant:
(define (recsum x . y)
(let ((accum (if (null? y) 0 (car y))))
(if (= x 0)
accum
(recsum (- x 1) (+ x accum)))))
Either way, it works as expected:
(recsum 10)
=> 55
Chicken has optional arguments. You can do it like this:
(define (sum n #!optional (acc 0))
(if (= n 0)
acc
(sum (- n 1) (+ acc n))))
However I will vote against using this as it is non standard Scheme. Chicken say they support SRFI-89: Optional positional and named parameters, but it seems it's an earlier version and the egg needs to be redone. Anyway when it is re-applied this should work:
;;chicken-install srfi-89 # install the egg
(use srfi-89) ; imports the egg
(define (sum n (acc 0))
(if (= n 0)
acc
(sum (- n 1) (+ acc n))))
Also your idea of using rest arguments work. However keep in mind that the procedure then will build a pair on the heap for each iteration:
(define (sum n . acc-lst)
(define acc
(if (null? acc-lst)
0
(car acc-lst)))
(if (= n 0)
acc
(sum (- n 1) (+ acc n))))
All of these leak internal information. Sometimes it's part of the public contract to have an optional parameter, but in this case it is to avoid writing a few more lines. Usually you don't want someone to pass a second argument and you should keep the internals private. The better way would be to use named let and keep the public contract as is.
(define (sum n)
(let loop ((n n) (acc 0))
(if (= n 0)
acc
(loop (- n 1) (+ acc n))))
I am trying to check if a number is prime using recursion. I was required to use a recursive helper function, but I am not sure how I should implement it.
I think I know the algorithm, but I've never tried to use a recursive helper function in Racket. This is my current thoughts:
See if n is divisible by i = 2
Set i = i + 1
If i^2 <= n continue.
If no values of i evenly divided n, then it must be prime.
This is what I have so far...
(define (is_prime n)
(if (<= n 1)
#f
(if (= (modulo n 2) 0)
#f
)
What would be a good approach using a recursive helper function??
Thanks!
Using a helper simply means that you should split your program in smaller parts, and possibly encapsulate loops with extra parameters in separate procedures - and in Scheme loops are frequently implemented via recursive calls. One (naïve) way to implement the is_prime procedure would be:
(define (is_prime n)
(cond ((<= n 1) #f)
((= n 2) #t)
((= (modulo n 2) 0) #f)
(else (check 3 n))))
; recursive helper
(define (check i n)
(cond ((> (* i i) n) #t)
((= (modulo n i) 0) #f)
(else (check (+ i 2) n))))
There are many ways to implement this procedure, and many possible optimizations; the above should be enough get you started.
(define (isPrimeHelper x k)
(if (= x k) #t
(if (= (remainder x k) 0) #f
(isPrimeHelper x (+ k 1)))))
(define ( isPrime x )
(cond
(( = x 0 ) #f)
(( = x 1 ) #f)
(( = x 2 ) #t)
( else (isPrimeHelper x 2 ) )))
I prefer this version.
I'm having a little trouble creating a recursive function in Scheme. I need to create a function called foo(x) that recursively does the addition of all the powers. For example foo(5) would be 5^4 + 4^3 + 3^2 + 2^1 + 1^0 = 701.
The stopping condition is if x = 0 then return zero. Else then return x^x-1 + foo(x-1)
Here's what I have so far for my function:
(define (foo x)
(cond ((zero? x) 0)
(else (+(expt(x (- x 1)))foo(- x 1)))))
You just have to be more careful with the parentheses, in particular notice that the correct way to call a procedure is like this: (foo x), instead of this: foo(x). This should work:
(define (foo x)
(cond ((zero? x) 0)
(else (+ (expt x (- x 1))
(foo (- x 1))))))
(foo 5)
=> 701
Allow me to ident the code. I just pasted it in DrRacket and hit CTRL+I then put the arguments to + on one line each:
(define (foo x)
(cond ((zero? x) 0)
(else (+ (expt (x (- x 1)))
foo
(- x 1)))))
So the base case is ok, but your default case looks very off. x is treated as a procedure since it has parentheses around it and - also uses x as if it's a number. It can't be both.
foo is not applied since it doesn't have parentheses around it so it evaluates to a procedure value, while + would expect all its arguments to be numeric.
The rules of Scheme are that parentheses matters. x and (x) are two totally different things. The first x can be any value, but (x) is an application so x have to evaluate to a procedure. Some exceptions are for special forms you need to know by heart like cond, and define but rather than that it's very important to know you change the meaning of a program by adding parentheses.
The correct definition of your procedure might be:
(define (foo x)
(if (zero? x)
0
(+ (expt x (- x 1))
(foo (- x 1)))))
(foo 5) ; ==> 701
Here I've changed cond to if since none of conds features were used. Seeing cond I expect either side effects or more than one predicate.
Inspired this post .
I trying to implement a fibonacci series with nested lambda -
(( (lambda (x) (x x)) ;; evaluate x on x
((lambda (fibo-gen)) ;; fibo-gen get another func as arg
(lambda (N it second first)
(cond ;; here the body of the above func ..
((= N 1) 1)
((= N 1) 1)
((= N it) (+ second first))
(else (fibo-gen (+ it 1) (+ second first) (second)))
)
)
)
)
5 1 1 1)
It's prompts r5rs:body: no expression in body in: (r5rs:body)
By my examination each function has a "body" here , so what I did wrong ?
Note that the implementation I trying to do here is iterative mode which avoid re-calculate previous series ..
Edit :
Another mode which also works -
(( (lambda (x) (x x)) ;; evaluate x on x
(lambda (fibo-gen) ;; fibo-gen body use another lambda ..
(lambda (N it second first)
(cond ;; here the body of the above func ..
((= N 1) 1)
((= N 2) 1)
((= N it) second)
(else ((fibo-gen fibo-gen) N (+ it 1) (+ second first) second))
)
)
)
)
5 1 1 1)
=> 8
Well, this is quite a contrived way to calculate fibonacci, but nevertheless possible:
(((lambda (x) (x x))
(lambda (fib-gen)
(lambda (it second first)
(if (zero? it)
first
((fib-gen fib-gen) (sub1 it) (+ first second) second)))))
10 1 0) ; here n = 10
=> 55
If you're aiming for a general way for writing a recursive function without using define, first implement the Y-Combinator:
(define (Y X)
((lambda (proc) (proc proc))
(lambda (proc)
(X (lambda args
(apply (proc proc) args))))))
With this, you can write anonymous recursive procedures with a variable number of arguments, for example:
((Y
(lambda (fib-gen)
(lambda (it second first)
(if (zero? it)
first
(fib-gen (sub1 it) (+ first second) second)))))
10 1 0) ; here n = 10
=> 55
(lambda (fibo-gen))
in the second line has no body.