Решение упражнения 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