Задание № 1.
Реализовать функции (@CHAR atom n) и (@FINDCHAR atom char n). Первая возвращает n-ый символ атома atom, а вторая возвращает номер позиции первого вхождения char в atom, при этом n задает номер позиции в atom, начиная с которой необходимо выполнять поиск. Если n опущено, то поиск начинается с начала аtom.
Реализация на lisp
Обзор функций
(DEFUN @CHAR (X N) ...)
X – символьный атом
N – номер символа в атоме
Осуществляет проверку входных данных и в случае отсутствия ошибок передаёт функции @char1 список символов, входящих в атом X и номер N. Также функция отлавливает тривиальные ситуации, когда результат заведомо NIL.
(DEFUN @CHAR1 (X N) ...)
X – список символов
N – номер символа в списке
Осуществляет рекурсивный поиск N-ого элемента в списке. Если N превышает длину списка, возвращает NIL, иначе возвращает N-ый элемент списка.
(defun @findchar (X Y N) ...)
X – символьный атом
Y – символ
N – номер
Осуществляет проверку входных данных и в случае отсутствия ошибок передаёт функции @findchar1 список символов, входящих в атом X, символ Y, номер N (если не был указан, то 1) и 1 (номер текущего элемента).
(defun @findchar1 (X Y N K) ...)
X – список символов
Y – символ
N – номер
K – номер текущего элемента в списке
Осуществляет рекурсивный поиск элемента Y в списке X. Возвращает номер позиции найденного элемента в списке (K), только если он не меньше N.
Исходный код
(DEFUN @CHAR (X N)
(COND
; Контроль корректности входных данных
((NOT (ATOM X)) ERROR!_WRONG_ATOM_ARGUMENT!)
((NOT (NUMBERP N)) ERROR!_WRONG_NUMBER_ARGUMENT!)
; Отлавливание тривиальной ситуации
((<= N 0) NIL)
; Вызов основной функции поиска
; (передаём список символов с помощью функции unpack)
(T (@CHAR1 (UNPACK X) N))
)
)
(DEFUN @CHAR1 (X N)
(COND
; Список пуст, результат – символ не найден
((NULL X) NIL)
; Достигнут нужный номер, результат – первый символ списка
((= N 1) (CAR X))
; Иначе – рекурсивный вызов функции с изменением параметров
(T (@CHAR1 (CDR X) (- N 1)))
)
)
(defun @findchar (X Y N)
(cond
; Контроль корректности входных данных
((not (atom X)) Error!_Wrong_atom_argument!)
((not (symbolp Y)) Error!_Wrong_symbol_argument!)
; Вызов основной функции (случай, когда N опущено)
((null N) (@findchar1 (unpack X) Y 1 1))
; Контроль корректности входных данных
((OR (not (numberp N)) (<= N 0))
Error!_Wrong_number_argument!)
; Вызов основной функции
(T (@findchar1 (unpack X) Y N 1))
)
)
(defun @findchar1 (X Y N K)
(cond
; Список пуст, результат – символ не найден
((null X) nil)
; Достигнут нужный символ и его номер не меньше N
; результат – первый символ списка
((and (EQ (car X) Y) (>= K N)) K)
; Иначе – рекурсивный вызов функции с изменением параметров
(T (@findchar1 (cdr X) Y N (+ K 1)))
)
)
Примеры
(@CHAR ‘(ABC) 2) —> ERROR!_WRONG_ATOM_ARGUMENT!
(@CHAR ‘ABCDEF ‘A) —> ERROR!_WRONG_NUMBER_ARGUMENT!
(@CHAR ‘ABCDEF -3) —> NIL
(@CHAR ‘ABCDEF 5) —> E
(@CHAR ‘ABCDEF 12) —> NIL
(@findchar ‘(1 2 3) ‘B 1) —> ERROR!_WRONG_ATOM_ARGUMENT!
(@findchar ‘ABCDEFBCK ‘B -3) —> ERROR!_WRONG_NUMBER_ARGUMENT!
(@findchar ‘ABCDEFBCK ‘B) —> 2
(@findchar ‘ABCDEFBCK ‘B 3) —> 7
(@findchar ‘ABCDEFXCK ‘B 3) —> NIL