Добавление элементов в список - 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))
Объяснение кода листинга программы
В этом коде:
- Создается список
*spare-nonterminals*
со значением(X Y Z)
, который представляет собой запас нетерминалов. - Определена функция
new-nonterminal()
, которая удаляет первый элемент из*spare-nonterminals*
и возвращает его. - Определены функции
make-production()
,lhs()
иrhs()
, которые используются для работы с продукциями. - Определена функция
remove-left-recursion-s()
, которая удаляет левую рекурсию из списка производств. - В функции
remove-left-recursion-s()
сначала создаются два списка:left-recurrent
, содержащий производства с левой рекурсией, иassociated
, содержащий производства с символомs
без рекурсии. - Затем создается новый нетерминал
x
с помощью функцииnew-nonterminal()
. - В функции
remove-left-recursion-s()
создаются три списка:c1
,c2
иc3
, которые содержат производства без рекурсии, с рекурсией без первого элемента в правой части и с рекурсией без первого элемента в правой части, соответственно. - Наконец, списки
c1
,c2
иc3
объединяются с помощью функцииnconc()
, и результат возвращается. Код принимает на вход список(s
ab d) (s s
ba) (s
cc b)
, и после удаления левой рекурсии результат будет(S
aB D X) (S
cC B X) (X
bA) (X
bA X)
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д