SGCG

…esto no es un subtítulo…

Ir a: contenido categorías calendario archivo suscripción

Volver arriba

Emacs Lisp en casos prácticos (3): cálculo de la letra del NIF (2)

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.

El problema

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:

  1. Se coge la parte numérica (los 7 dígitos anteriores al dígito de control).
  2. De este número, se calcula la suma de los 3 dígitos que ocupan las posiciones pares (el segundo, el cuarto y el sexto empezando por la izquierda).
  3. Del número del primer paso, se calculan los dobles de los dígitos de las posiciones impares (empezando por la izquierda, el doble del primer dígito, el doble del tercer dígito, el doble del quinto dígito y el doble del séptimo dígito).
  4. Se calcula la suma de todas las cifras que resultan del paso anterior.
  5. Se toma la cifra de las unidades de la suma del resultado del paso anterior y el resultado del segundo paso.
  6. Se calcula la diferencia entre el número 10 y el número calculado en el paso anterior. Si la diferencia es 10, se toma el valor 0.
  7. Si el CIF empieza por la letra «N», por la letra «P», por la letra «Q», por la letra «R», por la letra «S» o por la letra «W», el dígito de control es la letra correspondiente al número calculado en el paso anterior en la siguiente lista:
    0
    J
    1
    A
    2
    B
    3
    C
    4
    D
    5
    E
    6
    F
    7
    G
    8
    H
    9
    I
  8. Si es otra letra, entonces el dígito de control es directamente el número calculado en el sexto paso.

Vamos a completar nuestro código para calcular el dígito de control de un CIF.

Cálculo del dígito de control

Asumamos que disponemos de dos funciones:

nif--digitos
acepta un número y devuelve una lista de números con los dígitos correspondientes a la entrada;
nif--sumar-digitos
acepta un número y devuelve la suma de sus dígitos.

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)))))

Funciones auxiliares

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)))

Integración de la función de cálculo del dígito de control de un CIF

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)))

Código

El código de este artículo y el anterior está disponible aquí: nif.el


Categorías: Informática

Permalink: http://sgcg.es/articulos/2015/07/14/emacs-lisp-en-casos-practicos-3-calculo-de-la-letra-del-nif-2/