import Test.QuickCheck
import Data.List (unfoldr)
-- 1ª solución de decimalAmultiple
-- ===============================
decimalAmultiple1 :: [Integer] -> Integer -> [Integer]
decimalAmultiple1 bs n = reverse (aux bs n)
where aux _ 0 = []
aux (d:ds) m = r : aux ds q
where (q,r) = quotRem m d
-- 2ª solución de decimalAmultiple
-- ===============================
decimalAmultiple2 :: [Integer] -> Integer -> [Integer]
decimalAmultiple2 bs n = aux bs n []
where aux _ 0 xs = xs
aux (d:ds) m xs = aux ds q (r:xs)
where (q,r) = quotRem m d
-- 3ª solución de decimalAmultiple
-- ===============================
decimalAmultiple3 :: [Integer] -> Integer -> [Integer]
decimalAmultiple3 xs n = reverse (unfoldr f (xs,n))
where f (_ ,0) = Nothing
f ((y:ys),m) = Just (r,(ys,q))
where (q,r) = quotRem m y
-- Comprobación de equivalencia
-- ============================
-- La propiedad es
prop_decimalAmultiple :: InfiniteList (Positive Integer) -> Positive Integer -> Bool
prop_decimalAmultiple (InfiniteList xs _) (Positive n) =
all (== decimalAmultiple1 xs' n)
[decimalAmultiple2 xs' n,
decimalAmultiple3 xs' n]
where xs' = map getPositive xs
-- Comparación de eficiencia de decimalAmultiple
-- =============================================
-- La comparación es
-- λ> length (decimalAmultiple1 [2,7..] (10^(10^5)))
-- 21731
-- (0.45 secs, 486,085,256 bytes)
-- λ> length (decimalAmultiple2 [2,7..] (10^(10^5)))
-- 21731
-- (0.32 secs, 485,563,664 bytes)
-- λ> length (decimalAmultiple3 [2,7..] (10^(10^5)))
-- 21731
-- (0.44 secs, 487,649,768 bytes)
-- 1ª solución de multipleAdecimal
-- ===============================
multipleAdecimal1 :: [Integer] -> [Integer] -> Integer
multipleAdecimal1 xs ns = aux xs (reverse ns)
where aux (y:ys) (m:ms) = m + y * (aux ys ms)
aux _ _ = 0
-- 2ª solución de multipleAdecimal
-- ===============================
multipleAdecimal2 :: [Integer] -> [Integer] -> Integer
multipleAdecimal2 bs xs =
sum (zipWith (*) (reverse xs) (1 : scanl1 (*) bs))
-- Comprobación de equivalencia de multipleAdecimal
-- ================================================
-- La propiedad es
prop_multipleAdecimal :: InfiniteList (Positive Integer) -> [Positive Integer] -> Bool
prop_multipleAdecimal (InfiniteList xs _) ys =
multipleAdecimal1 xs' ys' == multipleAdecimal2 xs' ys'
where xs' = map getPositive xs
ys' = map getPositive ys
-- La comprobación es
-- λ> quickCheck prop_multipleAdecimal
-- +++ OK, passed 100 tests.
-- Comparación de eficiencia de multipleAdecimal
-- =============================================
-- La comparación es
-- λ> length (show (multipleAdecimal1 [2,3..] [1..10^4]))
-- 35660
-- (0.14 secs, 179,522,152 bytes)
-- λ> length (show (multipleAdecimal2 [2,3..] [1..10^4]))
-- 35660
-- (0.22 secs, 243,368,664 bytes)
-- Comprobación de las propiedades
-- ===============================
-- La primera propiedad es
prop_inversas :: InfiniteList (Positive Integer) -> Positive Integer -> Bool
prop_inversas (InfiniteList xs _) (Positive n) =
multipleAdecimal1 xs' (decimalAmultiple1 xs' n) == n
where xs' = map getPositive xs
-- Su comprobación es
-- λ> quickCheck prop_inversas
-- +++ OK, passed 100 tests.
-- la 2ª propiedad es
prop_coeficientes :: InfiniteList (Positive Integer) -> Positive Integer -> Bool
prop_coeficientes (InfiniteList xs _) (Positive n) =
and [0 <= c && c < b | (c,b) <- zip cs xs']
where xs' = map getPositive xs
cs = reverse (decimalAmultiple1 xs' n)
-- Su comprobación es
-- λ> quickCheck prop_coeficientes
-- +++ OK, passed 100 tests.