문제

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))))))
도움이 되었습니까?

해결책

나에게 괜찮아 보인다. 개선하고 싶은 구체적인 것이 있습니까?

당신은 다음과 같은 일을 할 수 있습니다.

(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)은 여러 인수를 처리하기 위해 쉽게 변환 될 수 있습니다.

다른 팁

이 책의 그 시점에서 제시된 개념 만 사용하면 다음과 같습니다.

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

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

내장을 사용하는 다음 코드로 수행했습니다. min, max, 그리고 square 절차. 그것들은 그 시점까지 텍스트에 도입 된 것을 사용하여 구현하기에 충분히 간단합니다.

(define (sum-of-highest-squares x y z)
   (+ (square (max x y))
      (square (max (min x y) z))))

이와 같은 것은 어떻습니까?

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

텍스트의 해당 지점까지 소개 된 개념 만 사용하여 다소 중요하다고 생각합니다, 다른 해결책은 다음과 같습니다.

(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)))))
(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))))
(define (f a b c) 
  (if (= a (min a b c)) 
      (+ (* b b) (* c c)) 
      (f b c a)))

Scott Hoffman 's와 일부 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)))))

목록을 정렬하고 정렬 된 목록의 첫 번째 및 두 번째 요소의 제곱을 추가 할 수도 있습니다.

(require (lib "list.ss")) ;; I use PLT Scheme

(define (exercise-1-3 a b c)
  (let* [(sorted-list (sort (list a b c) >))
         (x (first sorted-list))
         (y (second sorted-list))]
    (+ (* x x) (* y y))))

또 다른 방법은 다음과 같습니다.

#!/usr/bin/env mzscheme
#lang scheme/load

(module ex-1.3 scheme/base
  (define (ex-1.3 a b c)
    (let* ((square (lambda (x) (* x x)))
           (p (lambda (a b c) (+ (square a) (square (if (> b c) b c))))))
      (if (> a b) (p a b c) (p b a c))))

  (require scheme/contract)
  (provide/contract [ex-1.3 (-> number? number? number? number?)]))

;; tests
(module ex-1.3/test scheme/base
  (require (planet "test.ss" ("schematics" "schemeunit.plt" 2))
           (planet "text-ui.ss" ("schematics" "schemeunit.plt" 2)))
  (require 'ex-1.3)

  (test/text-ui
   (test-suite
    "ex-1.3"
    (test-equal? "1 2 3" (ex-1.3 1 2 3) 13)
    (test-equal? "2 1 3" (ex-1.3 2 1 3) 13)
    (test-equal? "2 1. 3.5" (ex-1.3 2 1. 3.5) 16.25)
    (test-equal? "-2 -10. 3.5" (ex-1.3 -2 -10. 3.5) 16.25)
    (test-exn "2+1i 0 0" exn:fail:contract? (lambda () (ex-1.3 2+1i 0 0)))
    (test-equal? "all equal" (ex-1.3 3 3 3) 18))))

(require 'ex-1.3/test)

예시:

$ mzscheme ex-1.3.ss
6 success(es) 0 failure(s) 0 error(s) 6 test(s) run
0

다른 사람들이 어떻게이 문제를 해결했는지 보는 것이 좋습니다. 이것은 내 해결책이었습니다.

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

나는 반복으로 해결했지만 Ashitaka와 (+ (square (max xy)) (square (max (min xy) z))) 솔루션이 더 좋습니다. 버전에서 z가 가장 작은 숫자 인 Isgreater? 불필요하게 느리고 회로적인 절차를 만듭니다.

(define (sum a b) (+ a b))
(define (square a) (* a a))
(define (greater a b ) 
  ( if (< a b) b a))
(define (smaller a b ) 
  ( if (< a b) a b))
(define (sumOfSquare a b)
    (sum (square a) (square b)))
(define (sumOfSquareOfGreaterNumbers a b c)
  (sumOfSquare (greater a b) (greater (smaller a b) c)))

나는 갔다 :

(define (procedure a b c)
    (let ((y (sort (list a b c) >)) (square (lambda (x) (* x x))))
        (+ (square (first y)) (square(second y)))))
;exercise 1.3
(define (sum-square-of-max a b c)
  (+ (if (> a b) (* a a) (* b b))
     (if (> b c) (* b b) (* c c))))

나는 이것이 가장 작고 가장 효율적인 방법이라고 생각합니다.

(define (square-sum-larger a b c)
 (+ 
  (square (max a b))
  (square (max (min a b) c))))

아래는 제가 생각해 낸 솔루션입니다. 코드가 작은 기능으로 분해 될 때 솔루션에 대해 추론하기가 더 쉽습니다.

            ; Exercise 1.3
(define (sum-square-largest a b c)
  (+ (square (greatest a b))
     (square (greatest (least a b) c))))

(define (greatest a b)
  (cond (( > a b) a)
    (( < a b) b)))

(define (least a b)
  (cond ((> a b) b)
    ((< a b) a)))

(define (square a)
  (* a a))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top