Scheme function as parameter - scheme

the program is supposed to use
(define (sum f n)
(if (= n 0)
(f 1)
(+ (f n) (sum f (- n 1)))))
(define (harm-term k)
(/ 1 k))
(define (harm-sum n)
(sum (harm-term 1) n))
to create a function called harm-sum that calculates the sum of harmonic series. But I keep getting the error
application:
not a procedure;
expected a procedure that can be applied to arguments
given: 3
arguments...:
for the sum function.

(define (sum f n)
(if (= n 0)
(f 1)
(+ (f n) (sum f (- n 1)))))
(define (harm-term k)
(/ 1 k))
(define (harm-sum n)
(sum (harm-term 1) n))
The way that you are eventually calling sum is wrong because you call sum with (harm-term 1) as the parameter that you are expecting a function for. (harm-term 1) clearly evaluates to a 1.
This means that when it is used later in sum as the parameter f it makes no sense (i.e. you eventually call (1 1))
You should be doing something like this:
(define (sum f n)
(if (= n 0)
(f 1)
(+ (f n) (sum f (- n 1)))))
(define (harm-term k)
(/ 1 k))
(define (harm-sum n)
(sum harm-term n)) ; the difference is the function itself is passed instead of the value the function returns for 1

Related

Scheme Binomial function using Pascal's Triangle

The binom procedure is suppose to return a function such that ((binom n) k a b) is the kth term in the binomial expansion of (a + b)^n.
This is my code.
(define (pascal row col)
(cond ((= col 1) 1)
((= row col) 1)
(else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col)))))
(define (binom n)
(lambda (k a b)
(cond ((or (= n 0) (= n k)) 1)
(else (binom (pascal k n)))) 1))
I am trying to fix the binom function. I think the formula is (n k) * a^k * b^(n-k). How should I write it in Scheme?
I think you got confused with the formulas, you're mixing up n, k, row and col.
I'd recommend writing down the formulas you want to program, name the variables on paper, then write the procedure using the same variable names.
With binom though, I'm not sure what your intent was.
Binom returns a lambda, that's all well and good.
But then in that lambda you make a recursive call to binom,
again returning a lambda? And then at the very end you basically ignore
the result you get from this and return 1?
In its current form binom will never return anything other than a lambda or 1.
Here's what I think you want:
(define (pascal n k)
(cond ((< n k) (error "not defined: k > n"))
((= k 1) n)
((= k 0) 1)
((= n k) 1)
(else (+ (pascal (- n 1) (- k 1)) (pascal (- n 1) k)))))
(define (binom n i a b)
(* (pascal n i) (expt a (- n i)) (expt b i)))

Factoring out a procedure

How could I use this procedure:
(define (sum f n )
(if (= n 1)
(f 1)
(+ ( f n ) (sum f (- n 1)))))
in order to redefine the following one?
(define (zeno n)
(cond ((= n 1)
(/ 1 2))
((> n 1)
(+ (zeno (- n 1))
(/ 1 (expt 2 n))))))
Basically, I am trying to create another function called zeno-sec that uses the sum function written above.
The procedure sum accepts another procedure f and you have to find that f. If you look at the second procedure zeno you can spot a possible body of f in the second clause of cond, that is (/ 1 (expt 2 n)). So f will be (lambda (a) (/ 1 (expt 2 a))). Combining it with sum, the zeno-sec will look like:
(define (zeno-sec n)
(sum (lambda (a)
(/ 1 (expt 2 a)))
n))
Edit: Maybe some clarifications could help. If you look at the two procedures, sum and zeno, you can see they have very similar structure: a conditional form and a recursion. Also if you switch the places of the subexpressions in the last expressions you will notice that they are almost the same:
(+ (sum f (- n 1))
(f n))
and
(+ (zeno (- n 1))
(/ 1 (expt 2 n)))
See how the call (zeno (- n 1)) resembles the (sum f (- n 1)) and the (f n) becomes (/ 1 (expt 2 n)). I hope that makes some sense.

Collatz function in scheme

So i'm trying to solve the collatz function iteratively in scheme but my test cases keep showing up as
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
1
(if (even? n) (collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1))
)
)
)
)
However, my test cases keep resulting in "#[constant 13 #x2]". What did I write wrong, if anything?
You forgot to call collatz-iter. Also, it's not clear what do you intend to do with counter, you just increment it, but never actually use its value - your procedure will always return 1 (assuming that the Collatz conjecture is true, which seems quite possible).
I'm guessing you intended to return the counter, so here's how to fix your procedure:
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
counter ; return the counter
(if (even? n)
(collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1)))))
(collatz-iter n 1)) ; call collatz-iter
And this is how it works for the examples in wikipedia:
(collatz 6)
=> 9
(collatz 11)
=> 15
(collatz 27)
=> 112
So basically we're counting the length of the Collatz sequence for a given number.
You should indent your code properly. With proper formatting, it's
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
1
(if (even? n)
(collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1))))))
which clearly has no body forms to execute, just an internal definition. You need to add a call to collatz-iter, like this:
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
1
(if (even? n)
(collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1)))))
(collatz-iter n 1))
(I'm not sure what your initial counter value should be. I'm assuming 1 is reasonable, but perhaps it should be zero?) Better yet, since the body it just a call to collatz-iter, you can make this a named let, which is more like your original code:
(define (collatz n)
(let iter ((n n) (counter 1))
(if (<= n 1)
1
(if (even? n)
(iter (/ n 2) (+ counter 1))
(iter (+ (* n 3) 1) (+ counter 1))))))
It's sort of like combining the internal definition with the single call to the local function. Once you've done this, though, you'll see that it always returns 1, when it eventually gets to the base case (assuming the Collatz conjecture is true, of course). Fixing this, you'll end up with:
(define (collatz n)
(let iter ((n n) (counter 1))
(if (<= n 1)
counter
(if (even? n)
(iter (/ n 2) (+ counter 1))
(iter (+ (* n 3) 1) (+ counter 1))))))
When I try to run your code in Racket I get the error:
no expression after a sequence of internal definitions
This is telling us that the collatz function conatains the collatz-iter definition, but no expression to call it (other than the recursive calls in collatz-iter). That can be fixed by adding a call to (collatz-iter n 0) as the last line in collatz.
However, when you run the program it always returns 1. Not very interesting. If instead you change it to return the value of counter you can see how many steps it took for the sequence to reach 1.
(define (collatz n)
(define (collatz-iter n counter)
(if (<= n 1)
counter
(if (even? n) (collatz-iter (/ n 2) (+ counter 1))
(collatz-iter (+ (* n 3) 1) (+ counter 1))
)
)
)
(collatz-iter n 0)
)
We can check it against a few examples given on the Wikipedia Collatz conjecture article.
> (collatz 6)
8
> (collatz 11)
14
> (collatz 27)
111
>

Does newtons method run 40 times?

The following is code that I wrote for newtons method:
(define (newtons-method f guess n)
(define (newtons-method-h guess k)
(if(= k n)
guess
(let ((next (- guess (/ (f guess) ((der f 0.1) guess)))))
(newtons-method-h next (+ k 1)))))
(newtons-method-h guess 0))
As well as code that I wrote to find square roots of numbers using newton's method:
(define (sqrt-newt n)
(newtons-method (lambda (x) (- (* x x) n)) 1.0 40))
I am wondering... Does sqrt-newt call newtons-method for 40 interations? I believe the answer is yes, but I am drawing a blank here.
Just add a counter to you code:
(define counter null) ; define a global variable
(define (newtons-method f guess n)
(define (newtons-method-h guess k)
(set! counter (add1 counter)) ; increment it at each call
(if (= k n)
guess
(let ((next (- guess (/ (f guess) ((der f 0.1) guess)))))
(newtons-method-h next (+ k 1)))))
(set! counter 0) ; initialize it before starting
(newtons-method-h guess 0))
(sqrt-newt 2) ; run the procedure
=> 1.4142135623730951
counter ; check the counter's value
=> 41
As you can see, the newtons-method-h procedure got called 41 times - one more than you expected, because the procedure gets invoked one last time when (= k n) and that's when the recursion ends.

+: expects type <number> as 2nd argument, given: #<void>;

I'm currently working on exercise 1.29 of SICP, and my program keeps giving me the following error:
+: expects type <number> as 2nd argument, given: #<void>; other arguments were: 970299/500000
Here's the code I'm running using racket:
(define (cube x)
(* x x x))
(define (integral2 f a b n)
(define (get-mult k)
(cond ((= k 0) 1)
((even? k) 4)
(else 2)))
(define (h b a n)
(/ (- b a) n))
(define (y f a b h k)
(f (+ a (* k (h b a n)))))
(define (iter f a b n k)
(cond ((> n k)
(+ (* (get-mult k)
(y f a b h k))
(iter f a b n (+ k 1))))))
(iter f a b n 0))
(integral2 cube 0 1 100)
I'm guessing the "2nd argument" is referring to the place where I add the current iteration and future iterations. However, I don't understand why that second argument isn't returning a number. Does anyone know how to remedy this error?
"2nd argument" refers to the second argument to +, which is the expression (iter f a b n (+ k 1)). According to the error message, that expression is evaluating to void, rather than a meaningful value. Why would that be the case?
Well, the entire body of iter is this cond expression:
(cond ((> n k)
(+ (* (get-mult k)
(y f a b h k))
(iter f a b n (+ k 1)))))
Under what circumstances would this expression not evaluate to a number? Well, what does this expression do? It checks if n is greater than k, and in that case it returns the result of an addition, which should be a number. But what if n is less than k or equal to k? It still needs to return a number then, and right now it isn't.
You're missing an else clause in your iter procedure. Ask yourself: what should happen when (<= n k) ? It's the base case of the recursion, and it must return a number, too!
(define (iter f a b n k)
(cond ((> n k)
(+ (* (get-mult k)
(y f a b h k))
(iter f a b n (+ k 1))))
(else <???>))) ; return the appropriate value

Resources