…esto no es un subtítulo…
2015-07-14
GNU Emacs es un editor de textos potentísimo. Por debajo, es un intérprete de Emacs Lisp, un lenguaje de programación de la familia de Lisp. En esta serie de artículos vamos a mostrar algunas formas de adaptar Emacs a nuestras necesidades con algunos casos prácticos.
En el artículo anterior y el presente artículo vemos la forma de completar cómo calcular el dígito de control de un NIF (como la letra del DNI) y completar un texto.
Las funciones para calcular el dígito de control del NIF del artículo anterior estaban incompletas: no cubrían los NIF de tipo CIF. Un CIF empieza por una letra mayúscula (a excepción de la «Ñ», la «X», la «Y» y la «Z»), sigue con 7 dígitos numéricos y termina con el dígito de control, que es un número o una letra en función de la letra inicial. El cálculo del dígito de control es más complicado que en el caso del DNI y el NIE; se hace de la manera siguiente:
Vamos a completar nuestro código para calcular el dígito de control de un CIF.
Asumamos que disponemos de dos funciones:
Con estas dos funciones, calcular el dígito de control es una mera aplicación directa del algoritmo expresado arriba:
(defun nif-digito-cif (cif)
"Devuelve el dígito de control correspondiente a un CIF."
(let* ((inicial (elt cif 0))
(digitos (nif--digitos (substring cif 1)))
(pares (list (nth 1 digitos)
(nth 3 digitos)
(nth 5 digitos)))
(impares (list (nth 0 digitos)
(nth 2 digitos)
(nth 4 digitos)
(nth 6 digitos)))
(suma-pares (apply '+ pares))
(dobles-impares (mapcar (lambda (numero)
(* 2 numero))
impares))
(sumas-impares (mapcar 'nif--sumar-digitos
dobles-impares))
(suma-impares (apply '+ sumas-impares))
(suma (+ suma-pares suma-impares))
(unidades (car (last (nif--digitos suma))))
(digito (mod (- 10 unidades) 10)))
(case inicial
((?N ?P ?Q ?R ?S ?W) (substring "JABCDEFGHI" digito (1+ digito)))
(otherwise (number-to-string digito)))))
Para la función nif--digitos que devuelve la lista de dígitos de un número, lo que hacemos es convertir el número a una cadena de texto (con number-to-string) de la que es fácil separar los dígitos corresopndientes (con split-string):
(defun nif--digitos (numero)
"Devuelve la lista de dígitos de un NÚMERO."
(mapcar 'string-to-number
(split-string (number-to-string numero) "" t)))
Para la función de sumar dígitos nif--sumar-digitos, explotamos la función nif--digitos que acabamos de escribir:
(defun nif--sumar-digitos (numero)
"Suma los dígitos de un NÚMERO."
(apply '+ (nif--digitos numero)))
Para poder usar las funciones nif-digito-de-control, nif-completar y nif-completar-region que desarrollamos en el artículo anterior, hace falta simplemente actualizar nif--calculador-del-digito-de-control para que devuelva la función para calcular el dígito de control de un CIF en los casos relevantes:
(defun nif--calculador-del-digito-de-control (nif)
(cond ((not (= 8 (length nif))) 'nif-digito-nulo)
((string-match "[0-9]\\{8\\}" nif) 'nif-letra-dni)
((string-match "[XYZ][0-9]\\{7\\}" nif) 'nif-letra-nie)
((string-match "[ABCDEFGHIJKLMNOPQRSTUVW][0-9]\\{7\\}" nif)
'nif-digito-cif)
(t 'nif-digito-nulo)))
El código de este artículo y el anterior está disponible aquí: nif.el
Categorías: Informática
Permalink: https://sgcg.es/articulos/2015/07/14/emacs-lisp-en-casos-practicos-3-calculo-de-la-letra-del-nif-2/