PDA

View Full Version : [LISP (Scheme)] Efficiency of My Program

Sinkingships7
September 12th, 2008, 01:31 AM
This program works, as in it does what is specified in the comment. But it seems a little too verbose. I was wondering if there was a more syntactically efficient way to write it.

;Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.

(define (sum-of-larger-squares x y z)
(cond
((and (> x z) (> y z))
(+ (* x x) (* y y)))
((and (> x y) (> z y))
(+ (* x x) (* z z)))
((and (> z x) (> y x))
(+ (* z z) (* y y)))))

(sum-of-larger-squares 2 10 5)

Sinkingships7
September 12th, 2008, 02:16 AM
I realized a better way to go about it would be:

(define (add-squares a b)
(+ (* a a) (* b b)))

(define (sum-of-larger-squares x y z)
(cond
((and (> x z) (> y z))
((and (> x y) (> z y))
((and (> z x) (> y x))

(sum-of-larger-squares 2 10 5)

If anyone has more ideas, feel free to contribute. I found a satisfactory answer, so this thread is no longer any sort of priority, but I'd always to be interested to see what you come up with.

DavidBell
September 12th, 2008, 07:52 AM
I don't do lisp so syntax is probably wrong, but why can't you do something like

(define (add-squares-if-first-two-bigger a b c)
(cond
((and (> a c) (> b c))
(+ (* a a) (* b b)))

(define (sum-of-larger-squares x y z)
((add-squares-if-first-two-bigger x y z)
(add-squares-if-first-two-bigger y z x)
(add-squares-if-first-two-bigger z x y))

(sum-of-larger-squares 2 10 5)

nvteighen
September 12th, 2008, 11:40 AM
I don't do lisp so syntax is probably wrong, but why can't you do something like

(define (add-squares-if-first-two-bigger a b c)
(cond
((and (> a c) (> b c))
(+ (* a a) (* b b)))

(define (sum-of-larger-squares x y z)
((add-squares-if-first-two-bigger x y z)
(add-squares-if-first-two-bigger y z x)
(add-squares-if-first-two-bigger z x y))

(sum-of-larger-squares 2 10 5)

Well, it's plainly wrong: this is what you get when talking about Lisp without knowing it... ;) (but, hey, why not learn it!)

(define (add-squares-if-first-two-bigger a b c)
(cond
((and (> a c) (> b c))
(+ (* a a) (* b b)))) ; you forgot a paren

(define (sum-of-larger-squares x y z)
(begin ; necessary
(add-squares-if-first-two-bigger x y z)
(add-squares-if-first-two-bigger y z x)
(add-squares-if-first-two-bigger z x y))) ; you forgot a paren

(sum-of-larger-squares 2 10 5)

Ok, the problem with that is the (begin ...), when you group with it is undefined by the standard. Usually it is the last value computed, but what if the condition is met for the first procedure and not the others? Then, your result gets lost because of the following procedures you called.

Now, back to the OP:
What I'd do is to call add-squares and determine arguments upon the conditions. Why? Because add-squares is always called and the "variant" part are the arguments.

So, I create a procedure local to add-squares that examinates the arguments and packs the correct pair into a cons. This is captured by a local variable called args... And then, we just call add-squares using selecting the elements in the pair.

This ensures a very nice modularity. If you want to add or remove conditions, you just change the local function!

In code:

(define (add-squares a b)
(+ (* a a)
(* b b)))

(define (sum-of-larger-squares x y z)
(define (choose x y z)
(cond
((and (> x z) (> y z))
(cons x y))
((and (> x y) (> z y))
(cons x z))
((and (> z x) (> y x))
(cons y z))))
(let ((args (choose x y z)))
(add-squares (car args) (cdr args))))

(sum-of-larger-squares 2 10 5)