Skip to content

Instantly share code, notes, and snippets.

@nihilismus
Created May 9, 2017 12:39
Show Gist options
  • Save nihilismus/73357f63b17d19c8e42d29604bfd6bd5 to your computer and use it in GitHub Desktop.
Save nihilismus/73357f63b17d19c8e42d29604bfd6bd5 to your computer and use it in GitHub Desktop.
Dígito verificador del RFC (México) y RUT (Chile) en Clojure.
(ns plf.rfc)
;; Registro Federal de Contribuyentes (México)
;; El Registro Federal de Contribuyentes (o RFC) es una clave que requiere
;; toda persona física o moral en México para realizar cualquier actividad
;; económica lícita por la que esté obligada a pagar impuestos a toda persona
;; moral, con algunas excepciones.
;; - https://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(M%C3%A9xico)
;; Procedimiento para calcular el dígito verificador del Registro Federal de Contribuyentes
;; http://solucionfactible.com/sfic/capitulos/timbrado/rfc-digito-verificador.jsp
(defn vmap [función vector-de-entrada]
(letfn [(recursividad [f xs ys]
(if (empty? xs)
ys
(recursividad f
(rest xs)
(conj ys (f (first xs))))))]
(recursividad función vector-de-entrada [])))
(defn vfilter [función vector-de-entrada]
(letfn [(recursividad [f xs ys]
(if (empty? xs)
ys
(recursividad f
(rest xs)
(if (f (first xs))
(conj ys (first xs))
ys))))]
(recursividad función vector-de-entrada [])))
(defn vreduce [función valor-inicial vector-de-entrada]
(letfn [(recursividad [f vf xs]
(if (empty? xs)
vf
(recursividad f
(f vf (first xs))
(rest xs))))]
(recursividad función valor-inicial vector-de-entrada)))
(defn vzip [vector-de-entrada-1 vector-de-entrada-2]
(letfn [(recursividad [xs ys zs]
(if (or (empty? xs) (empty? ys))
zs
(recursividad (rest xs)
(rest ys)
(conj zs [(first xs) (first ys)]))))]
(recursividad vector-de-entrada-1 vector-de-entrada-2 [])))
(defn vzipWith [función vector-de-entrada-1 vector-de-entrada-2]
(vmap (fn [par]
(función (first par) (last par)))
(vzip vector-de-entrada-1 vector-de-entrada-2)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn anexo3-carácter-a-número [carácter]
(let [carácter-número {\0 0
\1 1
\2 2
\3 3
\4 4
\5 5
\6 6
\7 7
\8 8
\9 9
\A 10
\B 11
\C 12
\D 13
\E 14
\F 15
\G 16
\H 17
\I 18
\J 19
\K 20
\L 21
\M 22
\N 23
\& 24
\O 25
\P 26
\Q 27
\R 28
\S 29
\T 30
\U 31
\V 32
\W 33
\X 34
\Y 35
\Z 36
\space 37
\Ñ 38}]
(if (nil? (carácter-número carácter))
-1
(carácter-número carácter))))
(defn vproducto [vector-de-entrada]
(vreduce * 1 vector-de-entrada))
(defn vsumatoria [vector-de-entrada]
(vreduce + 0 vector-de-entrada))
(defn cadena-de-caracteres-a-vector [cadena-de-caracteres]
(vreduce conj [] cadena-de-caracteres))
(defn vector-de-caracteres-a-números [vector-de-entrada]
(vmap anexo3-carácter-a-número
vector-de-entrada))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn rfc-con-formato-erroneo? [rfc]
(let [rfc-separado (vector-de-caracteres-a-números
(cadena-de-caracteres-a-vector rfc))]
(or (not= 12 (count rfc))
(not= 0 (count (vfilter neg? rfc-separado))))))
(defn dígito-verificador [rfc]
(if (rfc-con-formato-erroneo? rfc)
\u0000
(let [rfc-separado (vector-de-caracteres-a-números
(cadena-de-caracteres-a-vector rfc))
módulo-once (rem (vsumatoria
(vzipWith *
rfc-separado
[13 12 11 10 9 8 7 6 5 4 3 2]))
11)
número-a-dígito (fn [número]
({0 \0
1 \A
2 \9
3 \8
4 \7
5 \6
6 \5
7 \4
8 \3
9 \2
10 \1
11 \0} número))]
(número-a-dígito módulo-once))))
(defn es-válido? [rfc]
(= (last rfc)
(dígito-verificador
(vreduce str "" (vreduce conj [] (butlast rfc))))))
(ns plf.rut)
;; Rol Único Tributario (Chile)
;; El Rol Único Tributario, conocido también por el acrónimo RUT, es
;; un número único implantado en Chile, que fue establecido como
;; identificación tributaria por el Decreto con Fuerza de Ley N° 3
;; del 29 de enero de 1969.
;; - https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario
;; Comprobar Rut (Digito Verificador) [implementación en JavaScript]
;; https://estebanfuentealba.wordpress.com/2009/09/25/comprobar-rut-digito-verificador-javascript/
;;
;; Qué Es La Programación Funcional? [implementación en Python y Haskell]
;; http://www.programando.org/blog/2012/11/que-es-la-programacion-funcional/
(defn vmap [función vector-de-entrada]
(letfn [(recursividad [f xs ys]
(if (empty? xs)
ys
(recursividad f
(rest xs)
(conj ys (f (first xs))))))]
(recursividad función vector-de-entrada [])))
(defn vfilter [función vector-de-entrada]
(letfn [(recursividad [f xs ys]
(if (empty? xs)
ys
(recursividad f
(rest xs)
(if (f (first xs))
(conj ys (first xs))
ys))))]
(recursividad función vector-de-entrada [])))
(defn vreduce [función valor-inicial vector-de-entrada]
(letfn [(recursividad [f vf xs]
(if (empty? xs)
vf
(recursividad f
(f vf (first xs))
(rest xs))))]
(recursividad función valor-inicial vector-de-entrada)))
(defn vzip [vector-de-entrada-1 vector-de-entrada-2]
(letfn [(recursividad [xs ys zs]
(if (or (empty? xs) (empty? ys))
zs
(recursividad (rest xs)
(rest ys)
(conj zs [(first xs) (first ys)]))))]
(recursividad vector-de-entrada-1 vector-de-entrada-2 [])))
(defn vzipWith [función vector-de-entrada-1 vector-de-entrada-2]
(vmap (fn [par]
(función (first par) (last par)))
(vzip vector-de-entrada-1 vector-de-entrada-2)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn rut-carácter-a-número [carácter]
(let [carácter-número {\0 0
\1 1
\2 2
\3 3
\4 4
\5 5
\6 6
\7 7
\8 8
\9 9}]
(if (nil? (carácter-número carácter))
-1
(carácter-número carácter))))
(defn vproducto [vector-de-entrada]
(vreduce * 1 vector-de-entrada))
(defn vsumatoria [vector-de-entrada]
(vreduce + 0 vector-de-entrada))
(defn cadena-de-caracteres-a-vector [cadena-de-caracteres]
(vreduce conj [] cadena-de-caracteres))
(defn vector-de-caracteres-a-números [vector-de-entrada]
(vmap rut-carácter-a-número vector-de-entrada))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn rut-con-formato-erroneo? [rut]
(let [número-rut-separado (vector-de-caracteres-a-números
(cadena-de-caracteres-a-vector rut))]
(or (not= 8 (count rut))
(not= 0 (count (vfilter neg? número-rut-separado))))))
(defn dígito-verificador [rut]
(if (rut-con-formato-erroneo? rut)
\u0000
(let [número-rut-separado (vector-de-caracteres-a-números
(cadena-de-caracteres-a-vector rut))
módulo-once (rem (vsumatoria
(vzipWith *
número-rut-separado
[3 2 7 6 5 4 3 2]))
11)
número-a-dígito (fn [número]
({0 \0
1 \K
2 \9
3 \8
4 \7
5 \6
6 \5
7 \4
8 \3
9 \2
10 \1
11 \0} número))]
(número-a-dígito módulo-once))))
(defn es-válido? [rut]
(= (last rut)
(dígito-verificador
(vreduce str "" (vreduce conj [] (butlast rut))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment