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

30 January, 2008 (22:10) | Решения упражнений

Не устаю восхищаться удачным подбором упражнений в книге. Фактически упражнения – это логическое продолжение основного текста, которые дают дополнительную пищу для размышлений и позволяют увидеть скрытые нюансы.

Обобщенная процедура накопления accumulate-n строится поразительно просто. Достаточно лишь взять в соответствующих местах все первые элементы набора последовательностей и все “хвосты” последовательностей, то есть задействовать всеми любимые car и cdr:

(define (accumulate-n op init seqs) 
    (if (null? (car seqs)) 
        nil 
        (cons (accumulate op init (map car seqs)) 
              (accumulate-n op init (map cdr seqs)))))

Comments

Comment from Rokker Ruslan
Date: February 13, 2014, 12:57 pm

По поводу дополнительной пищи для размышлений. Это упражнение можно представить как диаграмму потока сигналов. В роли перечислителя у нас будет процедура, которая строит список, элементы которого являются в свою очередь списками. Список первых элементов, список вторых элементов… … список n-ых элементов.
Далее сигнал с перечислителя попадает в отображение, которое расчитывает сумму каждого списка. Далее (этот рункт можно пропустить) сигнал попадает в накопитель, где строится список всех сумм.

Перечислитель:
(define (enumerate-items sequences)
(if (null? (car sequences))
null
(cons (map car sequences)
(enumerate-items (map cdr sequences)))))

Тогда accumulate-n можно выразить следующим способом:
(define (accumulate-n op seqs)
(accumulate cons
null
(map op
(enumerate-items seqs))))

Построим операцию находящую сумму элементов списка (давайте без accumulate):
(define (sum sequence)
(if (null? sequence)
0
(+ (car (sequence))
(sum (cdr sequence)))))

Вызов accumulate-n:
(accumulate-n sum (list (list 1 2 3)
(list 4 5 6)
(list 7 8 9)
(list 10 11 12))

И того, мы решили задачу выразив её как операции над последовательностями.

Write a comment