fork download
  1. ;; Функция вычисляет суммы чисел на каждом уровне вложенности списка lst
  2. (defun calculate-level-sums (lst)
  3. (prepare-result (calculate-level-sums-helper lst 1 '())))
  4. ;; Рекурсивная функция, которая проходит по списку lst на заданном уровне level, накапливая суммы чисел в аккумуляторе acc. Аккумулятор acc - это список пар
  5.  
  6. (defun calculate-level-sums-helper (lst level acc)
  7.  
  8. (cond
  9. ((null lst) acc) ; Базовый случай: если список пуст, возвращает аккумулятор
  10. (t (let ((head (car lst)) ; Берет первый элемент списка
  11. (tail (cdr lst))) ; Берет остаток списка
  12. (multiple-value-bind (new-acc remaining-tail) ; Обрабатывает текущий элемент
  13. (process-item head level acc) ; Функция process-item определяет, что делать с элементом
  14. (calculate-level-sums-helper tail level new-acc)))))) ; Рекурсивно вызывает себя для остатка списка
  15.  
  16. ;; Обработка одного элемента item на заданном уровне level
  17. (defun process-item (item level acc)
  18.  
  19.  
  20. (cond
  21. ((numberp item) ; Если элемент - число
  22. (values (update-level-sum acc level item) nil)) ; Обновляет сумму для уровня и возвращает новый аккумулятор
  23. ((listp item) ; Если элемент - список
  24. (values (calculate-level-sums-helper item (1+ level) acc) nil)) ; Рекурсивно вызывает себя для списка, увеличив уровень
  25. (t (values acc nil)))) ; Если элемент - не число и не список (например, символ), просто игнорируем его
  26.  
  27. ;; Обновление аккумулятора acc суммой для заданного уровня level
  28. (defun update-level-sum (acc level value)
  29. (let ((existing (assoc level acc))) ; Ищет существующую запись для уровня
  30. (if existing ; Если уровень уже есть в аккумуляторе
  31. (let ((new-acc (remove existing acc :test #'equal))) ; Удаляет старую запись
  32. (cons (list level (+ value (cadr existing))) new-acc)) ; Добавляет обновленную запись с новой суммой
  33. (cons (list level value) acc)))) ; Иначе, добавляет новую пару (уровень value) в аккумулятор
  34.  
  35. ;; Подготавка результата
  36. (defun prepare-result (acc)
  37. (if (assoc 1 acc)
  38. (sort acc #'< :key #'car)
  39. (sort (cons '(1 0) acc) #'< :key #'car)))
  40.  
  41. ;; Тесты
  42. (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))
  43. (format t "~a~%" (calculate-level-sums '(a b c))) ; ((1 0))
  44. (format t "~a~%" (calculate-level-sums '(1 (2 (3))))) ; ((1 1) (2 2) (3 3))
  45. (format t "~a~%" (calculate-level-sums'(1 (2 3 (4 (5 6)))))) ; ((1 1) (2 5) (3 4) (4 11))
  46.  
Success #stdin #stdout #stderr 0.01s 9440KB
stdin
Standard input is empty
stdout
((1 0) (2 7) (3 9) (4 17) (5 3))
((1 0))
((1 1) (2 2) (3 3))
((1 1) (2 5) (3 4) (4 11))
stderr
Warning: reserving address range 0x80000c0000...0x1fffffffffff that contains memory mappings. clisp might crash later!
Memory dump:
  0x8000000000 - 0x80000bffff
  0x15126b400000 - 0x15126b6e4fff
  0x15126b815000 - 0x15126b839fff
  0x15126b83a000 - 0x15126b9acfff
  0x15126b9ad000 - 0x15126b9f5fff
  0x15126b9f6000 - 0x15126b9f8fff
  0x15126b9f9000 - 0x15126b9fbfff
  0x15126b9fc000 - 0x15126b9fffff
  0x15126ba00000 - 0x15126ba02fff
  0x15126ba03000 - 0x15126bc01fff
  0x15126bc02000 - 0x15126bc02fff
  0x15126bc03000 - 0x15126bc03fff
  0x15126bc80000 - 0x15126bc8ffff
  0x15126bc90000 - 0x15126bcc3fff
  0x15126bcc4000 - 0x15126bdfafff
  0x15126bdfb000 - 0x15126bdfbfff
  0x15126bdfc000 - 0x15126bdfefff
  0x15126bdff000 - 0x15126bdfffff
  0x15126be00000 - 0x15126be03fff
  0x15126be04000 - 0x15126c003fff
  0x15126c004000 - 0x15126c004fff
  0x15126c005000 - 0x15126c005fff
  0x15126c168000 - 0x15126c16bfff
  0x15126c16c000 - 0x15126c16cfff
  0x15126c16d000 - 0x15126c16efff
  0x15126c16f000 - 0x15126c16ffff
  0x15126c170000 - 0x15126c170fff
  0x15126c171000 - 0x15126c171fff
  0x15126c172000 - 0x15126c17ffff
  0x15126c180000 - 0x15126c18dfff
  0x15126c18e000 - 0x15126c19afff
  0x15126c19b000 - 0x15126c19efff
  0x15126c19f000 - 0x15126c19ffff
  0x15126c1a0000 - 0x15126c1a0fff
  0x15126c1a1000 - 0x15126c1a6fff
  0x15126c1a7000 - 0x15126c1a8fff
  0x15126c1a9000 - 0x15126c1a9fff
  0x15126c1aa000 - 0x15126c1aafff
  0x15126c1ab000 - 0x15126c1abfff
  0x15126c1ac000 - 0x15126c1d9fff
  0x15126c1da000 - 0x15126c1e8fff
  0x15126c1e9000 - 0x15126c28efff
  0x15126c28f000 - 0x15126c325fff
  0x15126c326000 - 0x15126c326fff
  0x15126c327000 - 0x15126c327fff
  0x15126c328000 - 0x15126c33bfff
  0x15126c33c000 - 0x15126c363fff
  0x15126c364000 - 0x15126c36dfff
  0x15126c36e000 - 0x15126c36ffff
  0x15126c370000 - 0x15126c375fff
  0x15126c376000 - 0x15126c378fff
  0x15126c37b000 - 0x15126c37bfff
  0x15126c37c000 - 0x15126c37cfff
  0x15126c37d000 - 0x15126c37dfff
  0x15126c37e000 - 0x15126c37efff
  0x15126c37f000 - 0x15126c37ffff
  0x15126c380000 - 0x15126c386fff
  0x15126c387000 - 0x15126c389fff
  0x15126c38a000 - 0x15126c38afff
  0x15126c38b000 - 0x15126c3abfff
  0x15126c3ac000 - 0x15126c3b3fff
  0x15126c3b4000 - 0x15126c3b4fff
  0x15126c3b5000 - 0x15126c3b5fff
  0x15126c3b6000 - 0x15126c3b6fff
  0x55d026f83000 - 0x55d027073fff
  0x55d027074000 - 0x55d02717dfff
  0x55d02717e000 - 0x55d0271ddfff
  0x55d0271df000 - 0x55d02720dfff
  0x55d02720e000 - 0x55d02723efff
  0x55d02723f000 - 0x55d027242fff
  0x55d02771e000 - 0x55d02773efff
  0x7ffda0da7000 - 0x7ffda0dc7fff
  0x7ffda0dcf000 - 0x7ffda0dd2fff
  0x7ffda0dd3000 - 0x7ffda0dd4fff