
;; Функция вычисляет суммы чисел на каждом уровне вложенности списка lst
(defun calculate-level-sums (lst)

;; Рекурсивная функция, которая проходит по списку lst на заданном уровне level.
;;Накапливает суммы чисел в аккумуляторе acc. Аккумулятор acc - это список пар 
 
(defun calculate-level-sums-helper (lst level acc)

  (cond
    ((null lst) acc) ; Базовый случай: если список пуст, возвращает аккумулятор
    (t (let ((head (car lst))  ; Берет первый элемент списка
             (tail (cdr lst))) ; Берет остаток списка
         (multiple-value-bind (new-acc remaining-tail)  ; Обрабатывает текущий элемент
           (process-item head level acc) ; Функция process-item определяет, что делать с элементом
           (calculate-level-sums-helper tail level new-acc)))))) ; Рекурсивно вызывает себя для остатка списка

;; Обработка одного элемента item на заданном уровне level
(defun process-item (item level acc)
 
   (cond
    ((numberp item) ; Если элемент - число
     (values (update-level-sum acc level item) nil)) ; Обновляет сумму для уровня 
    ((listp item) ; Если элемент - список
     (values (calculate-level-sums-helper item (1+ level) acc) nil)) ; Рекурсивно вызывает себя для списка, увеличив уровень
    (t (values acc nil)))) ; Если элемент - не число и не список, игнорирует его

;; Обновление аккумулятора acc суммой для заданного уровня level
(defun update-level-sum (acc level value)
  (let ((existing (assoc level acc))) ; Ищет существующую запись для уровня
    (if existing ; Если уровень уже есть в аккумуляторе
        (let ((new-acc (remove existing acc :test #'equal))) ; Удаляет старую запись
          (cons (list level (+ value (cadr existing))) new-acc)) ; Добавляет обновленную запись с новой суммой
        (cons (list level value) acc)))) ; Иначе, добавляет новую пару (уровень value) в аккумулятор

;; Подготавка результата
(defun prepare-result (acc)

      (sort (cons '(1 0) acc) #'< :key #'car))) ; Иначе, добавляет (1 0) и сортирует

;; Тесты
(format t "~a~%" (calculate-level-sums '(a (b (4 (2 e (3) k 15) e 5) 7)))) ; ((1 0) (2 7) (3 9) (4 17) (5 3))
(format t "~a~%" (calculate-level-sums '(a b c))) ; ((1 0))
(format t "~a~%" (calculate-level-sums '(1 (2 (3))))) ; ((1 1) (2 2) (3 3))
(format t "~a~%" (calculate-level-sums'(1 (2 3 (4 (5 6)))))) ; ((1 1) (2 5) (3 4) (4 11))
