Задача Хэмминга о порождении чисел
Существует знаменитая задача, впервые сформулированная Р. Хэммингом: породить в возрастающем порядке и без повторений все положительные целые числа, у которых нет других простых делителей, кроме
2, 3
и
5
. Очевидное решение состоит в том, чтобы перебирать все натуральные числа по очереди и проверять, есть ли у них простые множители помимо
2, 3
и
5
. Однако эта процедура весьма неэффективна, поскольку чем больше числа, тем меньшая их доля соответствует условию. Применим альтернативный подход: назовем искомый поток чисел
S
и обратим внимание на следующие факты:
•
S
начинается с
1
.
• Элементы
(scale-streams 2)
также принадлежат
S
.
• То же верно и для
(scale-stream S 3)
и
(scale-stream S 5)
.
• Других элементов
S
нет.
Теперь требуется только соединить элементы из этих источников. Для этого мы определяем процедуру
merge
, которая сливает два упорядоченных потока в один упорядоченный поток, убирая при этом повторения:
(define (merge s1 s2)
(cond ((stream-null? s1) s2)
((stream-null? s2) s1)
(else
(let ((s1car (stream-car s1))
(s2car (stream-car s2)))
(cond ((< s1car s2car)
(cons-stream s1car (merge (stream-cdr s1) s2)))
((> s1car s2car)
(cons-stream s2car (merge s1 (stream-cdr s2))))
(else
(cons-stream s1car
(merge (stream-cdr s1)
(stream-cdr s2)))))))))
Тогда требуемый поток можно получить с помощью
merge
таким образом:
(define S (cons-stream 1 (merge <??> <??>)))
Заполните пропуски в местах, обозначенных знаком
<??>
.
Комментарии отсутствуют.