elpanov.com » Обучение » Рекурсии урок 2



Рекурсии в AutoLISP урок 2

Возьмем последний пример из первого урока. Там из списка с числами получался список 3D точек, но бывают случаи, когда нужны только 2D точки. Тогда этот код будет выглядеть так:

 
(setq lst '(1 2 3 4 5 6 7 8 9))

(defun rec_lst_2d (lst)
  (if lst
    (cons
      (list
        (car lst)
        (cadr lst)
      ) ;_  list
      (rec_lst_2d (cdddr lst))
    ) ;_  cons
  ) ;_  if
) ;_  defun
 
 

Вызывать:

 
(rec_lst_2d lst)
 
 

получаем

 
'((1 2) (4 5) (7 8))
 
 

И наконец, то же самое, но для списка 2D точек, их можно получить после Vla-Get-Coordinates отличие в том, что количество элементов — чётное.

 
(setq lst '(1 2 3 4 5 6 7 8))
(defun rec_lst_2d_pt (lst)
  (if lst
    (cons
      (list
        (car lst)
        (cadr lst)
      ) ;_  list
      (rec_lst_2d_pt (cddr lst))
    ) ;_  cons
  ) ;_  if
) ;_  defun
 
 

Вызывать:

 
(rec_lst_2d_pt lst)
 
 

получаем

 
'((1 2) (3 4) (5 6) (7 8))
 
 

Надеюсь, что после всех приведенных функций, уже не составит большого труда понять сам алгоритм и сделать рекурсию с простым перебором элементов. Рассмотрим вариант использования функции рекурсии для создания списка. Допустим, у нас есть два числа 5 и 8, необходимо получить список, последовательно заполненный цифрами, начиная с 5 и заканчивая 8 с шагом 1 Нужно получить:

 
'(5 6 7 8)
 
 

Рекурсия:

 
(defun rec_2i_lst (a b)
  (if (<= a b)
    (cons a (rec_2i_lst (1+ a) b))
  ) ;_  if
) ;_  defun
 
 

Вызывать:

 
(setq a 5 b 8)
(rec_2i_lst a b)
 
 

Разберем, как она работает. Поскольку, мы объявляем A B как аргументы, вне функции они остаются неизменными, но внутри нее, мы можем их изменять! Значит можно организовать цикл с условием:

 
(<= a b)
 
 

и после каждого добавления в список элемента будем увеличивать A

 
(1+ a)
 
 

до тех пор, пока условие выполняется. На этот раз я не буду разворачивать код, а покажу вычисления, для каждого цикла и вместо переменных вставлю их значения: цикл 1:

 
(if (<= 5 8)
  (cons 5 (rec_2i_lst (1+ 5) 8))
) ;_  if
 
 

результат:

 
'(5 6 7 8)
 
 

цикл 2:

 
(if (<= 6 8)
  (cons 6 (rec_2i_lst (1+ 6) 8))
) ;_  if
 
 

результат:

 
'(6 7 8)
 
 

цикл 3:

 
(if (<= 7 8)
  (cons 7 (rec_2i_lst (1+ 7) 8))
) ;_  if
 
 

результат:

 
'(7 8)
 
 

цикл 4:

 
(if (<= 8 8)
  (cons 8 (rec_2i_lst (1+ 8) 8))
) ;_  if
 
 

результат:

 
'(8)
 
 

цикл 5:

 
(if (<= 9 8)
  (cons 9 (rec_2i_lst (1+ 9) 8))
) ;_  if
 
 

результат:

 
 NIL 
  
  

Формирование списка получается так:

 
(cons
  5
  (cons
    6
    (cons
      7
      (cons
        8
        nil
      ) ;_  cons
    ) ;_  cons
  ) ;_  cons
) ;_  cons

Старая версия сайта, доступна здесь.