Ответ 1
непроверенная. Обратите внимание, что процедура append-list
, которую я определил, фактически возвращает список, заканчивающийся на sos2
. Это уместно (и правильно делать) здесь, но не является вообще.
(define cart-product
(lambda (sos1 sos2)
(if (null? sos1) '()
(append-list
(cart-prod-sexpr (car sos1) sos2)
(cart-product (cdr sos1) sos2)))))
(define cart-prod-sexpr
(lambda (s sos)
(if (null? sos) '()
(cons
(list s (car sos))
(cart-prod-sexpr s (cdr sos))))))
(define append-list
(lambda (sos1 sos2)
(if (null? sos1) sos2
(cons
(car sos1)
(append-list (cdr sos1) sos2)))))
Обратите внимание, что если списки имеют размер n, тогда для получения списка размера O (n 2) потребуется время O (n 3). Используя обычный Я только что реализовал обычный append
, вместо этого возьмет O (n 4).append
, не осознавая этого. Если вы хотите взять O (n 2), вы должны быть более умными. Как и в этом непроверенном коде.
(define cart-product
(lambda (sos1 sos2)
(let cart-product-finish
(lambda (list1-current list2-current answer-current)
(if (null? list2-current)
(if (null? list1-current)
answer-current
(cart-product-finish (car list1-current) sos2 answer-current))
(cart-product-finish list1-current (car sos2)
(cons (cons (cdr list1-current) (cdr list2-current)) answer-current))))
(cart-product-finish list1 '() '())))
В случае, если у меня есть ошибка, идея состоит в том, чтобы рекурсивно перебирать все комбинации элементов в первом и втором, причем каждый из них заменяет answer-current
на cons
еще одной комбинацией, за которой следует все остальное. уже нашли. Благодаря оптимизации хвостового вызова это должно быть эффективным.