Напишите функцию format+ - Lisp
Формулировка задачи:
Напишите функцию format+, которая поддерживает все возможности функции format, но вдобавок позволяет обрабатывать форматную директиву ~z, предназначенную для форматирования страхового номера индивидуального лицевого счета (СНИЛС) гражданина РФ.
СНИЛС должен форматироваться следующим образом: ABC-DEF-GHI-CC, где ABC, DEF и GHI – группы из трех цифр, а CC (контрольная сумма) – группа из двух цифр. Контрольная сумма рассчитывается следующим образом:
1. Находится сумма произведений цифр номера на номер их позиции, то есть A*9+B*8+C*7+D*6+E*5+F*4+G*3+H*2+I.
2. Находится остаток от деления суммы на 101 и из него берутся две младших цифры, они и являются контрольной суммой.
Аргументом директивы ~z может являться либо целое положительное число, либо строка. Если в числе не хватает значащих цифр, то слева оно дополняется нулями до 11 разрядов. Строка может содержать не более 11 десятичных цифр. В случае недопустимых аргументов и других ошибок считать СНИЛС неправильно сформированным и отображать как [bad SNILS].
Примеры форматирования с помощью директивы ~z:
(format+ t "Vasya's ~a = ~z" "SNILS" "00202203341") ==> Vasya's SNILS = 002-022-033-41
(format+ nil "~d: ~z, ~d: ~z" 1 120344511 2 "111abc22233344") ==> "1: [bad SNILS], 2: [bad SNILS]"
Замечание:
Для упрощения задания можно считать, что директива ~z не поддерживается внутри условной директивы ~[, внутри циклов ~{ и в сочетании с директивами выбора аргументов типа ~:*
Подсказка:
Разумеется, реализовывать самостоятельно все директивы функции format не нужно. Нужно обработать директиву ~z и затем передать новую форматную строку и измененный список аргументов в функцию format.
Решение задачи: «Напишите функцию format+»
textual
Листинг программы
(defun check-dig (s) (dotimes (i (length s) t) (when (null (search (subseq s i (+ i 1)) "0123456789")) (return nil)))) (defun check-sum (n) (let ((c 1) (s 0)) (dotimes (i 9 (mod (mod s 101) 100)) (setf s (+ s (* c (mod n 10)))) (setf n (truncate (/ n 10))) (setf c (+ c 1))))) (defun fsnils (snils) (let ((sn 0) (ds "") (cs 0)) (cond ((not (or (integerp snils) (stringp snils))) "[bad SNILS]") ((and (integerp snils) (> snils 99999999999)) "[bad SNILS]") ((and (stringp snils) (not (check-dig snils))) "[bad SNILS]") (t (when (stringp snils) (setf sn (parse-integer snils)) (setf ds (format nil "~11,'0d" sn))) (when (integerp snils)(setf ds (format nil "~11,'0d" snils))) (setf cs (check-sum (truncate (/ (parse-integer ds) 100)))) (if (/= cs (mod (parse-integer ds) 100)) "[bad SNILS]" (concatenate 'string (subseq ds 0 3) "-" (subseq ds 3 6) "-" (subseq ds 6 9) "-" (format nil "~2d" cs))))))) (defun prepro (fstr arglist) (let ((fstro "") (argo nil) (pz 0)) (loop (setf pz (search "~z" fstr)) (when (null pz) (return (list (concatenate 'string fstro fstr) (append argo arglist)))) (setf pz (search "~" fstr)) (when (null pz) (return (list (concatenate 'string fstro fstr) (append argo arglist)))) (when (plusp pz) (setf fstro (concatenate 'string fstro (subseq fstr 0 pz))) (setf fstr (subseq fstr pz))) (cond ((string= "z" (subseq fstr 1 2)) (setf fstro (concatenate 'string fstro (fsnils (car arglist)))) (setf fstr (subseq fstr 2)) (setf arglist (cdr arglist))) (t (setf fstro (concatenate 'string fstro (subseq fstr 0 2))) (setf fstr (subseq fstr 2)) (setf argo (append argo (list (car arglist)))) (setf arglist (cdr arglist))))))) (defun format+ (to fstr &rest arglist) (let ((p (prepro fstr arglist))) (apply #'format (append (list to (car p)) (cadr p)))))
Объяснение кода листинга программы
- Функция
check-dig
принимает строкуs
и возвращаетnil
, если строка не является допустимым контрольным числом, иначе возвращаетt
. - Функция
check-sum
принимает числоn
и возвращает контрольную сумму в виде строки. - Функция
fsnils
принимает строкуsnils
и возвращает строку с проверенным и отформатированным контрольным числом. - Функция
prepro
принимает строкуfstr
и список аргументовarglist
и возвращает список, где первый элемент - отформатированная строка без значений, второй элемент - список аргументов без значений. - Функция
format+
принимает символto
, строкуfstr
и список аргументовarglist
и возвращает отформатированную строку.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д