سؤال

وأنا أحاول أن تعلم مخطط عبر 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)))))

وهذا (بروك ع) يمكن تحويلها بسهولة للتعامل مع أي عدد من الحجج.

نصائح أخرى

وفقط باستخدام المفاهيم الواردة في تلك المرحلة من الكتاب، أود أن تفعل ذلك:

(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 @ فرينود #scheme)؛ كما يتطلب SRFI 1 و <لأ href = "HTTP: // srfi .schemers.org / srfi-26 / srfi-26.html "يختلط =" noreferrer "> 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)))

ومع سكوت هوفمان وبعض IRC مساعدة I تصحيح قانون بلدي الخاطئ، ومن هنا

(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 و((مربع (ماكس س ص)) (مربع (بحد أقصى (دقيقة س ص) ض)) +) حلول أفضل، لأنه في نسخة بلدي، وإذا ض هو أصغر عدد ، 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