Инверсия атомов для заданного списка - Lisp

Узнай цену своей работы

Формулировка задачи:

Инверсия состоит в замене местами атома самого высокого уровня атомом самого низкого уровня. Количество атомов на обоих уровнях одинаково. Имена атомов на указанных уровнях различны. Пример 1.
Листинг программы
  1. (a (b (c)) d (e (f))) ==>(c (b (a)) f (e (d)))

Решение задачи: «Инверсия атомов для заданного списка»

textual
Листинг программы
  1. ;; Список пар (уровень атом)
  2.  
  3. (defun lv-list (lst &optional (lv 0) (r nil))
  4.   (cond ((null lst) r)
  5.         ((atom (car lst)) (lv-list (cdr lst) lv (cons (list lv (car lst)) r)))
  6.         (t (let ((rr (lv-list (car lst) (+ lv 1) nil)))
  7.               (append rr (lv-list (cdr lst) lv r))))))  
  8.  
  9. ==> lv-list
  10.  
  11. (lv-list '(a (b (c)) d (e (f))))
  12.  
  13. ==> ((2 c) (1 b) (2 f) (1 e) (0 d) (0 a))
  14.  
  15. ;; Список внутренних и внешних  атомов
  16.  
  17. (defun max-min (lst)
  18.    (let* ((lvl (mapcar 'car lst))
  19.           (ma  (apply 'max lvl))
  20.           (mi  (apply 'min lvl)))
  21.     (list (mapcar 'cadr (remove-if #'(lambda (x) (< (car x) ma)) lst))
  22.           (mapcar 'cadr (remove-if #'(lambda (x) (> (car x) mi)) lst)))))
  23.  
  24.  
  25. ==> max-min
  26.  
  27. (max-min (lv-list '(a (b (c)) d (e (f)))))
  28.  
  29. ==> ((c f) (d a))
  30.  
  31. ;; Замена
  32.  
  33. (defun repl-atom (lst x y)
  34.   (mapcar #'(lambda (z)
  35.               (cond ((eq z x) y)
  36.                     ((eq z y) x)
  37.                     ((listp z) (repl-atom z x y))
  38.                     (t z))) lst))
  39.  
  40. ==> repl-atom
  41.  
  42. (repl-atom '(a s d (j u) ((jj))) 'j 'jj)
  43.  
  44. ==> (a s d (jj u) ((j)))
  45.  
  46. ;; Решение задачи:
  47.  
  48. (defun task (lst &optional (ma-mi (max-min (lv-list lst))))
  49.   (cond ((and (null (car ma-mi)) (null (cadr ma-mi))) lst)
  50.         (t (let ((x (caar ma-mi))
  51.                  (y (car (cadr ma-mi))))
  52.              (task (repl-atom lst x y) (list (cdr (car ma-mi)) (cdr (cadr ma-mi))))))))
  53.  
  54. ==> task
  55.  
  56. (task '(a (b (c)) d (e (f))))
  57.  
  58. ==> (f (b (d)) c (e (a)))

Объяснение кода листинга программы

  1. lv-list - функция, которая принимает список и два опциональных параметра, первый из которых - уровень атомов, а второй - результат предыдущего вызова функции. Если список пуст, возвращается результат предыдущего вызова. Если первый элемент списка - атом, то добавляется новый элемент с уровнем и атомом, а результат предыдущего вызова обновляется. Если первый элемент списка - не атом, то рекурсивно вызывается функция lv-list для его первого элемента, уровень увеличивается на единицу, а результат предыдущего вызова объединяется с новым списком, начинающимся с добавленного элемента.
  2. max-min - функция, которая принимает список и возвращает два элемента: максимальный и минимальный уровень атомов в списке. Сначала создается список уровней атомов, затем с помощью функции max находится максимальное значение уровня, а с помощью функции min - минимальное значение уровня. Затем из списка удаляются элементы с уровнем, меньшим максимального значения, и добавляются элементы с уровнем, большим минимального значения.
  3. repl-atom - функция, которая принимает список и три элемента: старый атом, новый атом и уровень, и заменяет все вхождения старого атома на новый атом на указанном уровне. Если элемент - атом, и он соответствует старому атому, он заменяется на новый атом. Если элемент - список, функция рекурсивно вызывается для каждого его элемента.
  4. task - функция, которая принимает список и два опциональных параметра: список пар внутренних и внешних атомов и список пар уровней внутренних и внешних атомов. Если список пуст, возвращается результат предыдущего вызова. Если первый элемент списка - атом, то он заменяется на второй элемент пары внешних атомов, а результат предыдущего вызова передается следующей итерации. Если первый элемент списка - не атом, то рекурсивно вызывается функция task для его первого элемента, уровень увеличивается на единицу, а результат предыдущего вызова объединяется с новым списком, начинающимся с добавленного элемента.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 4.167 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы