Я попытался выучить алгоритмы в SICP , которые находят набор пересечений двух отсортированных списков
(defun intersection-set (set1 set2)
(if (or (null set1) (null set2))
'()
(let ((x1 (car set1)) (x2 (car set2)));;
(cond ((= x1 x2)
(cons x1
(intersection-set (cdr set1)
(cdr set2))))
((< x1 x2)
(intersection-set (cdr set1) set2))
((< x2 x1)
(intersection-set set1 (cdr set2)))))))
Начнем со сравнения начальных элементов, x1 и x2,из двух комплектов. Если x1 равно x2, то это дает элемент пересечения, а остальная часть пересечения - это пересечение cdrs двух множеств. Предположим, однако, что x1 меньше, чем x2. Поскольку x2 является наименьшим элементом в set2, мы можем сразу заключить, что x1 не может появиться где-либо в set2 и, следовательно, не находится на пересечении. Следовательно, пересечение равно пересечению множества set2 с cdr множества set1. Аналогично, если x2 меньше, чем x1, то пересечение дается пересечением set1 с cdr set2. Вот процедура:
Я нахожу deque.popleft
в значительной степени car
cdr
стиль и переписать его как
def intersection_set(list1, list2):
if isinstance(list1, list):
list1 = deque(list1)
list2 = deque(list2)
if len(list1) == 0 or len(list2) == 0:
return []
x1, x2 = list1[0], list2[0]
if x1 == x2:
list1.popleft()
list2.popleft()
return [x1] + intersection_set(list1, list2)
if x1 < x2:
list1.popleft()
return intersection_set(list1, list2)
else:
list2.popleft()
return intersection_set(list1, list2)
intersection_set([2, 3], [3, 4])
## -- End pasted text --
Out[9]: [3]
Проблемы очевидны, popleft не такочень помогает в концептуальном понимании,
Есть ли сходства с car
cdr
, я могу воспользоваться рекурсивным и бинарным взаимоисключением.