Acciones

Relación 7

De Informática de 1º de Matemáticas [Curso 2021-22, Grupo 3]

Revisión del 12:50 15 ene 2022 de Alvgalber (discusión | contribs.)
(difs.) ← Revisión anterior | Revisión actual (difs.) | Revisión siguiente → (difs.)
-- I1M 2021-22: Rel_7.hs
-- El algoritmo de Luhn
-- Departamento de Ciencias de la Computación e I.A.
-- Universidad de Sevilla
-- =====================================================================

-- ---------------------------------------------------------------------
-- § Introducción                                                     --
-- ---------------------------------------------------------------------

-- El objetivo de esta relación es estudiar un algoritmo para validar
-- algunos identificadores numéricos como los números de algunas tarjetas
-- de crédito; por ejemplo, las de tipo Visa o Master Card.
--
-- El algoritmo que vamos a estudiar es el algoritmo de Luhn consistente
-- en aplicar los siguientes pasos a los dígitos del número de la
-- tarjeta.
--    1. Se invierten los dígitos del número; por ejemplo, [9,4,5,5] se
--       transdforma en [5,5,4,9].
--    2. Se duplican los dígitos que se encuentra en posiciones impares
--       (empezando a contar en 0); por ejemplo, [5,5,4,9] se transforma
--       en [5,10,4,18].
--    3. Se suman los dígitos de cada número; por ejemplo, [5,10,4,18]
--       se transforma en 5 + (1 + 0) + 4 + (1 + 8) = 19.
--    4. Si el último dígito de la suma es 0, el número es válido; y no
--       lo es, en caso contrario.
--
-- A los números válidos, los llamaremos números de Luhn.

-- ---------------------------------------------------------------------
-- Ejercicio 1. Definir la función
--    digitosInv :: Integer -> [Integer]
-- tal que (digitosInv n) es la lista de los dígitos del número n. en
-- orden inverso. Por ejemplo,
--    digitosInv 320274  ==  [4,7,2,0,2,3]
-- ---------------------------------------------------------------------

-- Álvaro Galisteo:

digitosInv :: Integer -> [Integer]
digitosInv n = reverse [read [x] :: Integer | x <- show n ]

-- ---------------------------------------------------------------------
-- Ejercicio 2. Definir la función
--    doblePosImpar :: [Integer] -> [Integer]
-- tal que (doblePosImpar ns) es la lista obtenida doblando los
-- elementos en las posiciones impares (empezando a contar en cero y
-- dejando igual a los que están en posiciones pares. Por ejemplo,
--    doblePosImpar [4,9,5,5]    ==  [4,18,5,10]
--    doblePosImpar [4,9,5,5,7]  ==  [4,18,5,10,7]
-- ---------------------------------------------------------------------

-- Álvaro Galisteo:

doblePosImpar :: [Integer] -> [Integer]
doblePosImpar [] = []
doblePosImpar [x] = [x]
doblePosImpar (x:y:xs) = [x,2*y] ++ doblePosImpar xs

-- ---------------------------------------------------------------------
-- Ejercicio 3. Definir la función
--    sumaDigitos :: [Integer] -> Integer
-- tal que (sumaDigitos ns) es la suma de los dígitos de ns. Por
-- ejemplo,
--    sumaDigitos [10,5,18,4] = 1 + 0 + 5 + 1 + 8 + 4 =
--                            = 19
-- ---------------------------------------------------------------------

-- Álvaro Galisteo:

sumaDigitos :: [Integer] -> Integer
sumaDigitos ns = sum [sumaDigitos' x | x <- ns] 

sumaDigitos' :: Integer -> Integer
sumaDigitos' n = sum [read [x] :: Integer | x <- show n ]

-- ---------------------------------------------------------------------
-- Ejercicio 4. Definir la función
--    ultimoDigito :: Integer -> Integer
-- tal que (ultimoDigito n) es el último dígito de n. Por ejemplo,
--    ultimoDigito 123 == 3
--    ultimoDigito   0 == 0
-- ---------------------------------------------------------------------

-- Álvaro Galisteo:

ultimoDigito :: Integer -> Integer
ultimoDigito n = mod n 10 

-- ---------------------------------------------------------------------
-- Ejercicio 5. Definir la función
--    luhn :: Integer -> Bool
-- tal que (luhn n) se verifica si n es un número de Luhn. Por ejemplo,
--    luhn 5594589764218858  ==  True
--    luhn 1234567898765432  ==  False
-- ---------------------------------------------------------------------

-- Álvaro Galisteo:

luhn :: Integer -> Bool
luhn n = ultimoDigito (sumaDigitos (doblePosImpar (digitosInv n))) == 0