Is my implementation of SICP Exercise 1.3 going in the right direction? - scheme

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))))

Related

MIT-Scheme SICP Exercise_1.11 -- object #t is not applicable

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!.

Scheme function won't print

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

what is wrong this scheme code?

I'm studying sicp.
this question is ex 1.3.
I can't understand why this code is problem.
please help me.. TT
here's the code.
(define (test a b c)
(cond ((and (< a b) (< a c)) (+ (* b b) (* c c))
(and (< b a) (< b c)) (+ (* a a) (* c c))
(else (+ (* b b) (* c c)))
))
(test 1 2 3)
error is
Premature EOF on #[input-port 60 from buffer at #[mark 61 #[buffer 17]
166 left]
Your syntax for cond is wrong. Here is the same code with the correct syntax:
(define (test a b c)
(cond ((and (< a b) (< a c)) (+ (* b b) (* c c)))
((and (< b a) (< b c)) (+ (* a a) (* c c)))
(else (+ (* b b) (* c c)))))
However, your code is still wrong. Can you see why? (Hint: what does the else branch signify, and what expression should be there?)
Missing parentheses.
(define
(test a b c)
(cond
((and (< a b) (< a c)) (+ (* b b) (* c c)))
((and (< b a) (< b c)) (+ (* a a) (* c c)))
(else (+ (* b b) (* c c))))

Scheme quadratic function/square root check

Im want to make a function where rootcheck has a list L as input, L always is 3 atoms (a b c) where a is coefficient of x^2, b coef of x and c is the constant. it checks if the equation is quadratic, using discriminant (b^2 - 4ac) and should output this (num 'L) where num is the number of roots and L is a list that contains the roots themselves (using quadratic formula), L is empty in case of no roots. here is my code:
(define roots-2
(lambda (L)
(let ((d (- (* (cdr L) (cdr L)) (4 (car L) (caddr L))))))
(cond ((< d 0) (cons(0 null)))
((= d 0) (cons(1 null)))
(else((> d 0) (cons(2 null)))))
))
its giving me no expression in body error.
also I tried to code the quadratic function and even tried some that are online, one compiled fint but gave me an error when I inserted input this is the code for the quadratic function, NOT MINE!
(define quadratic-solutions
(lambda (a b c) (list (root1 a b c) (root2 a b c))))
(define root1
(lambda (a b c) (/ (+ (- b) (sqrt (discriminant a b c)))
(* 2 a))))
(define root2
(lambda (a b c) (/ (- (- b) (sqrt (discriminant a b c)))
(*2 a))))
(define discriminant
(lambda (a b c) (- (square b) (* 4 (* a c)))))
There are several mistakes in the code:
Some parentheses are incorrectly placed, use a good IDE to detect such problems. This is causing the error reported, the let doesn't have a body
You forgot to multiply in the 4ac part
You're incorrectly accessing the second element in the list
The else part must not have a condition
The output list is not correctly constructed
This should fix the errors, now replace null with the actual call to the function that calculates the roots for the second and third cases (the (< d 0) case is fine as it is):
(define roots-2
(lambda (L)
(let ((d (- (* (cadr L) (cadr L)) (* 4 (car L) (caddr L)))))
(cond ((< d 0) (list 0 null))
((= d 0) (list 1 null))
(else (list 2 null))))))
for the quadractic function part, I found a code online and tweaked it to provide both roots of a quadratic equation. returns a list of both roots
(define (solve-quadratic-equation a b c)
(define disc (sqrt (- (* b b)
(* 4.0 a c))))
(list (/ (+ (- b) disc) (* 2.0 a))
(/ (- (- b) disc) (* 2.0 a))
))

Problem with 'let' syntax in scheme

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)))

Resources