Решение упражнения 2.51 из SICP

6 February, 2008 (21:16) | Решения упражнений

2511.pngОпределение below напрямую абсолютно аналогично определению beside. Отличия только в том, как происходит разбиение исходной рамки на две. В beside исходная рамка (0.0, 0.0) – (1.0, 1.0) разбивается на две по вертикали : (0.0, 0.0) – (0.5, 1.0) и (0.5, 0.0) – (1.0, 1.0).  В below та же исходная рамка разбивается несколько иначе (по горизонтали): (0.0, 0.0) – (1.0, 0.5) и (0.0, 0.5) – (1.0, 1.0). Соответсвенно меняется split-point и координаты векторов. Результат выглядит так:

(define (below painter1 painter2) 
  (let ((split-point (make-vect 0.0 0.5))) 
    (let ((paint-bottom 
           (transform-painter painter1 
                              (make-vect 0.0 0.0) 
                              (make-vect 1.0 0.0) 
                              split-point)) 
          (paint-top 
           (transform-painter painter2 
                              split-point 
                              (make-vect 1.0 0.5) 
                              (make-vect 0.0 1.0)))) 
      (lambda (frame) 
         (paint-bottom frame) 
         (paint-top frame)))))

Теперь более интересная часть – определение below через beside и операции вращения. Несложно заметить, что результат below это почти повернутый на 90 градусов результат beside. Проблема, однако, в этом почти. Изображения в каждой из половин также поворачиваются на 90 градусов, что нам совершенно не нужно. Но эту проблему можно легко решить. Достаточно просто предварительно повернуть каждое из них на 90 градусов в противоположную сторону. На схеме ниже представлено два варианта действий, отличающихся порядком поворотов (по часовой или против часовой стрелки). Кликните на картинке для просмотра в увеличенном виде.

2511.png

Вспоминая теперь, что поворот на 90 градусов по часовой стрелке – это то же, что поворот на 270 градусов против часовой стрелки, можем записать такие два определения для below:

(define (below painter1 painter2) 
  (rotate-90 (beside (rotate-270 painter1) 
                     (rotate-270 painter2))))
(define (below painter1 painter2) 
  (rotate-270 (beside (rotate-90 painter2) 
                      (rotate-90 painter1))))
 

Все просто и красиво.

Write a comment