import Data.List (genericReplicate)
import Graphics.Gnuplot.Simple
import Test.QuickCheck
-- 1ª solución
-- ===========
sumaReducidaDigitosRepeticiones :: Integer -> Integer -> Integer
sumaReducidaDigitosRepeticiones n x =
sumaReducidaDigitos (repeticiones n x)
-- (repeticiones n x) es el número obtenido repitiendo n veces el x. Por
-- ejemplo,
-- repeticiones 3 24 == 242424
-- repeticiones 4 325 == 325325325325
repeticiones :: Integer -> Integer -> Integer
repeticiones n x = read (concat (genericReplicate n (show x)))
-- (sumaDigitos x) es la suma de los dígitos de x. Por ejemplo,
-- sumaDigitos 325 == 10
sumaDigitos :: Integer -> Integer
sumaDigitos x | x < 10 = x
| otherwise = b + sumaDigitos a
where (a,b) = divMod x 10
-- (sumaReducidaDigitos x) es el número obtenido a partir de x
-- reiterando la suma de los dígitos hasta obtener un número con sólo un
-- dígito. Por ejemplo,
-- sumaReducidaDigitos 24 == 6
-- sumaReducidaDigitos 325 == 1
sumaReducidaDigitos :: Integer -> Integer
sumaReducidaDigitos x | x < 10 = x
| otherwise = sumaReducidaDigitos (sumaDigitos x)
-- 2ª solución
-- ===========
sumaReducidaDigitosRepeticiones2 :: Integer -> Integer -> Integer
sumaReducidaDigitosRepeticiones2 n x =
sumaReducidaDigitos2 (n * sumaReducidaDigitos2 x)
sumaReducidaDigitos2 :: Integer -> Integer
sumaReducidaDigitos2 0 = 0
sumaReducidaDigitos2 x | y == 0 = 9
| otherwise = y
where y = x `mod` 9
-- Equivalencia de las definiciones
-- ================================
-- La propiedad es
prop_equiv :: Positive Integer -> Positive Integer -> Bool
prop_equiv (Positive n) (Positive x) =
sumaReducidaDigitosRepeticiones n x == sumaReducidaDigitosRepeticiones2 n x
-- La comprobación es
-- λ> quickCheck prop_equiv
-- +++ OK, passed 100 tests.
-- Comparación de eficiencia
-- =========================
-- λ> sumaReducidaDigitosRepeticiones (10^4) (10^4)
-- 1
-- (2.00 secs, 574,667,384 bytes)
-- λ> sumaReducidaDigitosRepeticiones2 (10^4) (10^4)
-- 1
-- (0.03 secs, 141,120 bytes)
-- Gráfica
-- =======
grafica :: Integer -> IO ()
grafica n =
plotList [Key Nothing]
[sumaReducidaDigitosRepeticiones2 k k | k <- [1..n]]