SICP Exercise 1.3 запрос на комментарии - PullRequest
22 голосов
/ 02 октября 2008

Я пытаюсь узнать схему через SICP. Упражнение 1.3 выглядит следующим образом: Определите процедуру, которая принимает три числа в качестве аргументов и возвращает сумму квадратов двух больших чисел. Пожалуйста, прокомментируйте, как я могу улучшить свое решение.

(define (big x y)
    (if (> x y) x y))

(define (p a b c)
    (cond ((> a b) (+ (square a) (square (big b c))))
          (else (+ (square b) (square (big a c))))))

Ответы [ 17 ]

28 голосов
/ 22 июля 2009

Используя только концепции, представленные в этой части книги, я бы сделал это:

(define (square x) (* x x))

(define (sum-of-squares x y) (+ (square x) (square y)))

(define (min x y) (if (< x y) x y))

(define (max x y) (if (> x y) x y))

(define (sum-squares-2-biggest x y z)
  (sum-of-squares (max x y) (max z (min x y))))
13 голосов
/ 02 октября 2008

big называется max. Используйте стандартные функции библиотеки, когда она там есть.

Мой подход другой. Вместо множества тестов я просто складываю квадраты всех трех, а затем вычитаю квадрат из наименьшего.

(define (exercise1.3 a b c)
  (let ((smallest (min a b c))
        (square (lambda (x) (* x x))))
    (+ (square a) (square b) (square c) (- (square smallest)))))

Предпочитаете ли вы этот подход или набор if тестов, конечно, решать вам.


Альтернативная реализация с использованием SRFI 95 :

(define (exercise1.3 . args)
  (let ((sorted (sort! args >))
        (square (lambda (x) (* x x))))
    (+ (square (car sorted)) (square (cadr sorted)))))

Как указано выше, но в виде одной строки (спасибо synx @ freenode #scheme); также требуется SRFI 1 и SRFI 26 :

(define (exercise1.3 . args)
  (apply + (map! (cut expt <> 2) (take! (sort! args >) 2))))
10 голосов
/ 05 октября 2009

Я сделал это с помощью следующего кода, который использует встроенные процедуры min, max и square. Их достаточно просто реализовать, используя только то, что было введено в текст до этого момента.

(define (sum-of-highest-squares x y z)
   (+ (square (max x y))
      (square (max (min x y) z))))
9 голосов
/ 04 марта 2009

Как насчет этого?

(define (p a b c)
  (if (> a b)
      (if (> b c)
          (+ (square a) (square b))
          (+ (square a) (square c)))
      (if (> a c)
          (+ (square a) (square b))
          (+ (square b) (square c)))))
4 голосов
/ 05 июля 2009

Используя только те понятия, которые были введены до этой точки текста, , что я считаю довольно важным , вот другое решение:

(define (smallest-of-three a b c)
        (if (< a b)
            (if (< a c) a c)
            (if (< b c) b c)))

(define (square a)
        (* a a))

(define (sum-of-squares-largest a b c) 
        (+ (square a)
           (square b)
           (square c)
           (- (square (smallest-of-three a b c)))))
4 голосов
/ 30 января 2012
(define (sum-sqr x y)
(+ (square x) (square y)))

(define (sum-squares-2-of-3 x y z)
    (cond ((and (<= x y) (<= x z)) (sum-sqr y z))
             ((and (<= y x) (<= y z)) (sum-sqr x z))
             ((and (<= z x) (<= z y)) (sum-sqr x y))))
4 голосов
/ 30 января 2012
(define (f a b c) 
  (if (= a (min a b c)) 
      (+ (* b b) (* c c)) 
      (f b c a)))
4 голосов
/ 02 октября 2008

Выглядит хорошо для меня, есть что-то конкретное, что вы хотите улучшить?

Вы можете сделать что-то вроде:

(define (max2 . l)
  (lambda ()
    (let ((a (apply max l)))
      (values a (apply max (remv a l))))))

(define (q a b c)
  (call-with-values (max2 a b c)
    (lambda (a b)
      (+ (* a a) (* b b)))))

(define (skip-min . l)
  (lambda ()
    (apply values (remv (apply min l) l))))

(define (p a b c)
  (call-with-values (skip-min a b c)
    (lambda (a b)
      (+ (* a a) (* b b)))))

И это (proc p) может быть легко преобразовано для обработки любого количества аргументов.

3 голосов
/ 10 декабря 2009

С помощью Скотта Хоффмана и некоторой помощи IRC я ​​исправил свой неисправный код, вот он

(define (p a b c)
    (cond ((> a b)
        (cond ((> b c)
            (+ (square a) (square b)))
            (else (+ (square a) (square c)))))
        (else
            (cond ((> a c)
                (+ (square b) (square a))))
             (+ (square b) (square c)))))
2 голосов
/ 27 июля 2018

Приятно видеть, как другие люди решили эту проблему. Это было мое решение:

(define (isGreater? x y z)
(if (and (> x z) (> y z))
(+ (square x) (square y))
0))

(define (sumLarger x y z)
(if (= (isGreater? x y z) 0)   
(sumLarger y z x)
(isGreater? x y z)))

Я решил это путем итерации, но мне больше нравятся решения Ашитаки и (+ (квадрат (max xy)) (квадрат (max (min xy) z))), так как в моей версии, если z - наименьшее число , лучше? вызывается дважды, создавая излишне медленную и обходную процедуру.

...