Вот простая рекурсивная функция для вычисления индексов:
(defun two-sum (list target &optional (pos 0))
(if (null (cdr list))
nil
(let ((p (my-position (- target (car list)) list)))
(if p
(list pos (+ pos p))
(two-sum (cdr list) target (1+ pos))))))
(defun my-position (element list &optional (pos 0))
(cond ((null list) nil)
((eql element (car list)) pos)
(t (my-position element (cdr list) (1+ pos)))))
Функция первоначально вызывается со списком и целью. Параметр pos
, который изначально не передается в функцию, автоматически присваивается 0, а в последующих вызовах он увеличивается на единицу, так что он отслеживает индекс текущего элемента списка.
Первое условие проверяет, содержит ли список менее двух элементов: если он пуст (или его cdr
пуст), результат равен nil
, поскольку решение невозможно (обратите внимание, что в Common Lisp (cdr nil)
nil
).
В противном случае мы вычисляем позицию «дополнения» числа в остальной части списка (обратите внимание, что position
является примитивной функцией, поэтому я назвал my-position
ее переписыванием) , Если элемент присутствует, мы возвращаем как pos
, так и (+ pos p)
(поскольку найденная позиция относительно текущей позиции), в противном случае (my-position
возвращает nil
, когда элемент не найден), мы возвращаемся к остальной части список.
Обратите внимание, что при использовании этого метода нет необходимости каждый раз рассматривать все элементы списка.