Добавление элементов в список - Lisp

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

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

Здравствуйте! Нужно многократно изменять значение списка в цикле (добавлять в него новые списки). Вне цикла данный код работает (формирование новых списков и добавление в главный список), но в цикле - нет (результат NIL).
(defun remove-left-recursion (g &optional g2)
    (setq v '(X Y Z))
    (loop for i in g do
        (if (equal (car i) (cadr i))
                (loop for j in g do
                    (cond ((and (not (equal i j)) (equal (car i) (car j)))
                            (cons (list (car v) (cddr i) (car v)) (cons (list (car v) (cddr i)) (cons (list (car i) (cdr j) (car v)) g2)))
                            (remove (car v) v)
                        )
                    )
 
                )
                (cons i g2)
        )
    )
)
 
(remove-left-recursion '((S "a" B D) (S S "b" A) (S "c" C B)))
Подскажите, в чем дело? Спасибо.

Решение задачи: «Добавление элементов в список»

textual
Листинг программы
(defparameter *spare-nonterminals* '(X Y Z) "A stock of unused nonterminals")
 
(defun new-nonterminal ()
  "Generate an unused nonterminal"
  (pop *spare-nonterminals*))
 
;;; Утилиты для продукций
 
(defun make-production (&key lhs rhs)
  (cons lhs rhs))
 
(defun lhs (production)
  (first production))
 
(defun rhs (production)
  (rest production))
 
;;; Проба пера -- удаление левой рекурсии для одного-единственного символа S
(defun remove-left-recursion-s (productions)
  ;; собираю сначала продукции, в которых есть рекурсия, потом с левой частью S, но без рекурсии
  (let ((left-recurrent (remove-if-not (lambda (p)
                                         (and (eq 's (lhs p))
                                              (eq (lhs p) (first (rhs p)))))
                                       productions))
        (associated (remove-if-not (lambda (p)
                                     (and (eq (lhs p) 's)
                                          (not (eq (lhs p) (first (rhs p))))))
                                   productions)))
    (let ((x (new-nonterminal)))
      ;; c1): беру все продукции без рекурсии и к правой части каждой из них добавляю Х
      (let ((c1 (mapcar (lambda (p) (make-production :lhs (lhs p) :rhs (append (rhs p) (list x)))) associated))
            ;; c2): беру все продукции с рекурсией и отбрасываю первый элемент в правой части
            (c2 (mapcar (lambda (p) (make-production :lhs x :rhs (rest (rhs p)))) left-recurrent))
            ;; c3): беру все продукции с рекурсией, отбрасываю первый элемент в правой части и добавляю Х
            (c3 (mapcar (lambda (p) (make-production :lhs x :rhs (append (rest (rhs p)) (list x)))) left-recurrent)))
        ;; объединяю полученное по предыдущим правилам. Мне, helter-у, можно nconc-ем
        (nconc c1 c2 c3)))))
 
> (remove-left-recursion-s '((s "a" b d) (s s "b" a) (s "c" c b)))
((S "a" B D X) (S "c" C B X) (X "b" A) (X "b" A X))

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

В этом коде:

  1. Создается список *spare-nonterminals* со значением (X Y Z), который представляет собой запас нетерминалов.
  2. Определена функция new-nonterminal(), которая удаляет первый элемент из *spare-nonterminals* и возвращает его.
  3. Определены функции make-production(), lhs() и rhs(), которые используются для работы с продукциями.
  4. Определена функция remove-left-recursion-s(), которая удаляет левую рекурсию из списка производств.
  5. В функции remove-left-recursion-s() сначала создаются два списка: left-recurrent, содержащий производства с левой рекурсией, и associated, содержащий производства с символом s без рекурсии.
  6. Затем создается новый нетерминал x с помощью функции new-nonterminal().
  7. В функции remove-left-recursion-s() создаются три списка: c1, c2 и c3, которые содержат производства без рекурсии, с рекурсией без первого элемента в правой части и с рекурсией без первого элемента в правой части, соответственно.
  8. Наконец, списки c1, c2 и c3 объединяются с помощью функции nconc(), и результат возвращается. Код принимает на вход список (sab d) (s sba) (scc b), и после удаления левой рекурсии результат будет (SaB D X) (ScC B X) (XbA) (XbA X).

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


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

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

5   голосов , оценка 4.2 из 5
Похожие ответы