Please tell me why the following Scheme function won't print the result. I'm using DrRacket.
#lang sicp
(define (sqr x) (* x x))
(define (sum_of_greatest_squares a b c)
(if(> a b)
(if(> a c)
(if(> b c)
((+ (sqr a) (sqr c))(+ (sqr a) (sqr b))))
(+ (sqr a) (sqr c))
)
(if(> b c)
(if (> a c)
((+ (sqr a) (sqr b))(+ (sqr b) (sqr c)))
(+ (sqr c) (sqr b))))
))
(sum_of_greatest_squares 3 4 5)
Its plain to see that you haven't been very detail-oriented with your learning. Your code contains countless mistakes and you've allowed yourself to bring habits from other languages into your learning of scheme. DrRacket clearly shows there's a syntax error with your program, so that's a good place to start.
The sections I have bolded are missing an else expression
(define (sum_of_greatest_squares a b c)
(if(> a b)
(if(> a c)
(if(> b c)
((+ (sqr a) (sqr c))(+ (sqr a) (sqr b))))
(+ (sqr a) (sqr c))
)
(if(> b c)
(if (> a c)
((+ (sqr a) (sqr b))(+ (sqr b) (sqr c)))
(+ (sqr c) (sqr b))))
))
The formatting of your code is bad and thus makes it harder to see where mistakes were made.
Moving along, here's another big mistake
((+ (sqr a) (sqr c))(+ (sqr a) (sqr b)))
You can't just put () wherever you want, like you can in some languages. () are used for procedure application in Lisp/Scheme/Racket.
Say a = 1, b = 2, and c = 3, the above line would be the equivalent of
((+ (sqr 1) (sqr 3))(+ (sqr 1) (sqr 2)))
((+ 1 9 )(+ 1 4 ))
(10 5)
The last line is (10 5) which says "apply the number 5 to the number 10" – which makes no sense.
You make the same mistake later in the code too. Try fixing up these problems first and then update your question.
ps: don't use snake_case names like sum_of_greatest_squares. Schemers typically would format that as sum-of-greatest-squares.
It's not immediately clear what your procedure is supposed to do anyway. My guess is that it's supposed to square the two largest inputs and then sum them.
You could do a huge hierarchy of if expressions to decide which two arguments to perform a computation with... but another way would be to always use the same two arguments to compute the result, but use if expressions to move the appropriate arguments into the correct place.
Consider this as a lateral alternative to your procedure
(define (sqr x) (* x x))
(define (sum-of-greatest-squares a b c)
(cond ((< a b) (sum-of-greatest-squares b c a))
((< b c) (sum-of-greatest-squares a c b))
(else (+ (sqr a) (sqr b)))))
This will always sum the squares of the two greatest numbers, but does so in a much cleaner way
Lastly, Jörg mentions that you're not actually printing anything anywhere. I know you mean to imply that DrRacket isn't showing the result of your program in the Interactions window. However, if you do want to explicitly print to the console, look at the display* and print* procedures
Related
This is my first post on StackOverflow. I have been working on Exercise 1.11 from SICP and feel I have a viable solution. In transferring from paper to Emacs I seem to have some syntax error that I am unaware of. I tried my best to double and triple check the parenthesis and solve it but the terminal is still giving me an 'object #t is not applicable' message. Could someone please point me in the right direction of how to fix the code so I can test its output properly?"
Exercise 1.11: A function f
is defined by the rule that:
f(n)=n
if n<3
, and
f(n)=f(n−1)+2f(n−2)+3f(n−3)
if n>=3
Write a procedure that computes f by means of a recursive process.
Write a procedure that computes f by means of an iterative process.
(define (f-recur n)
(if ((< n 3) n)
(+ (f(- n 1))
(* 2 (f(n-2)))
(* 3 (f(n-3)))))
(define (f-iter n)
(define (counter n)
(if (<= n 3) 0)
(- n 3))
(define (d n) (+ n (* 2 n) (* 3 n)))
(define (c n) (+ d (* 2 n) (* 3 n)))
(define (b n) (+ c (* 2 d) (* 3 n)))
(define (a n) (+ b (* 2 c) (* 3 d)))
(define (f a b c d counter)
(if ((> (+ counter 3) n) a)
(f (+ b (* 2 c) (* 3 d)) a b c (+ counter 1)))))
(cond ((= counter 0) d)
((= counter 1) c)
((= counter 2) b)
((= counter 3) a)
(else (f a b c d counter))))
I'm pretty sure SICP is looking for a solution in the manner of this iterative fibonnacci:
(define (fib n)
(define (helper n a b)
(if (zero? n)
a
(helper (- n 1) b (+ a b))))
(helper n 0 1))
Fibonacci is f(n)=f(n−1)+f(n−2) so I guess f(n)=f(n−1)+2f(n−2)+3f(n−3) can be made exactly the same way with one extra variable. Your iterative solution looks more like Fortran than Scheme. Try avoiding set!.
Exercise 1.3 in SICP asks to define a procedure that takes 3 numbers as arguments and returns the sum of the squares of the 2 largest numbers. I think I've gotten it correct but I wasn't totally sure if I've covered all cases. My implementation is as follows:
(define (bigsq a b c)
(cond ((and (> a b) (> b c)) (+ (* a a) (* b b)))
((and (> a b) (not (> b c))) (+ (* a a) (* c c)))
((> c a) (+ (* b b) (* c c)))
(else (+ (* a a) (* b b))))
Is there a way to write those first 2 conditions as one, as well? Also any comments on efficiency are welcome as well.
For starters, we could use a helper procedure for implementing the sum just once:
(define (sum x y)
(+ (* x x) (* y y)))
Now, for the conditions: given that the order doesn't matter - (sum a b) is the same as (sum b a), there's only 4 cases to consider, and we can avoid repeating some of the comparisons by nesting ifs:
(define (sum-max a b c)
(if (>= a b)
(if (>= b c)
(sum a b)
(sum a c))
(if (>= a c)
(sum b a)
(sum b c))))
I am trying to create program in Scheme (DrRacket) to solve roots of quadratic equation. I have also function to solve discriminant (function D). If discriminant is >0 function root should have on the output "point pair" (is that the correct word? english is not my native language) of both roots. Else it should give #f on the output.
(define na2
(lambda (x)
(* x x)))
(define D
(lambda (a b c)
(- (na2 b) (* 4 a c))))
(define roots
(lambda (a b c)
((if (> (D a b c) 0)
(cons (/ (+ (- b) (sqrt (D a b c))) (* 2 a)) (/ (- (- b) (sqrt (D a b c))) (* 2 a)))
#f)))
It gives me this:
> (roots 1 3 2)
>: contract violation
expected: real?
given: (-1 . -2)
argument position: 1st
other arguments...:
>
As you can see the correct output is there, but why the error?
Edit:
I corrected typo, as Parakram Majumdar helepd me, now it gives me
application: not a procedure;
expected a procedure that can be applied to arguments
given: (-1 . -2)
arguments...: [none]
Can someone please tell what am I doing wrong?
As discussed in the comments, the if statement should be written as follows:
(if cond then else)
where the condition would be :
(> (D a b c) 0)
So overall it should be:
(define roots
(lambda (a b c)
(if (> (D a b c) 0)
(cons (/ (+ (- b) (sqrt (D a b c))) (* 2 a))
(/ (- (- b) (sqrt (D a b c))) (* 2 a)))
#f
)))
I got home yesterday and decided to try and write a scheme program that would sort three numbers in ascending order. This is what I came up with:
(define a 3)
(define b 2)
(define c 1)
(define temp 0)
(cond
( (> a c) (set! temp c) (set! c a) (set! a temp))
( (> b c) (set! temp c) (set! c b) (set! b temp))
( (> a b) (set! temp b) (set! b a) (set! a temp))
( (> b c) (set! temp c) (set! b c) (set! b temp))
)
(display a)
(display b)
(display c)
Is that a functional way of solving the problem? What would you suggest?
Scheme has a builtin sort function that is actually faster in some cases than all the sort alorithms we use.
(sort < '(5 2 6))
returns
'(2 5 6)
The main problem that I see with your procedure is that you're only running a swap once. That's great if you can guarantee that one will always be in the middle of the other two, but I'm not so sure that it will always be the case. Also set! is kinda ugly and when I learned scheme my professor told me not to use it because it was resource intensive and there are better ways to do it. I would recommend putting them all in a list and then sorting them and pulling them out of the list if you want to do it that way.
I'm going through "Structure and Interpretation of Computer Programs" and I'm having a bit of trouble doing one of the exercises ( 2.1 ) . I'm coding in DrRacket in R5RS mode.
here's my code :
(define (make-rat n d)
(let (((c (gcd n d))
(neg (< (* n d) 0))
(n (/ (abs n) c))
(d (/ (abs d) c)))
(cons (if neg (- n) n) d))))
and here's the error message DrRacket is giving me:
let: bad syntax (not an identifier and expression for a binding) in: ((c (gcd n d)) (neg (< (* n d) 0)) (pn (/ (abs n) c)) (pd (/ (abs d) c)))
I think I've messed up let's syntax. but I'm not sure how to fix it.
I added an extra set of parentheses around the variable declarations, whoops.
Also, since I used c to define n and d, I had to change let into let* to make it work properly
my fixed code:
(define (make-rat n d)
(let* ((c (gcd n d))
(neg (< (* n d) 0))
(n (/ (abs n) c))
(d (/ (abs d) c)))
(cons (if neg (- n) n) d)))
As your edit indicates, you're using the c identifier prematurely. (Which is why it isn't working after fixing the syntax issue of the extra parenthesis.) Identifiers in "let" don't see each other. You'd need to nest your second three lets under the first.
(let ((c (gcd ...)))
(let ((...))
exps ...))
I don't recall when/if SICP introduces other let forms, but if you are stuck using a lot of nested lets, you can use let* in which each subsequent identifier is in the scope of all the previous. That is, the following two definitions are equivalent:
(define foo
(let* ((a 1)
(b (+ 1 a))
(c (+ 1 b)))
(+ 1 c)))
(define foo
(let ((a 1))
(let ((b (+ 1 a)))
(let ((c (+ 1 b)))
(+ 1 c)))))
The scoping rules of the different let forms can be a bit much for a beginner, unfortunately.
Try this:
(define (make-rat n d)
(let ([c (gcd n d)]
[neg (< (* n d) 0)]
[n (/ (abs n) c)]
[d (/ (abs d) c)])
(cons (if neg
(- n)
n)
d)))