import Test.QuickCheck (Property, (==>), quickCheck)
-- 1ª solución
-- ===========
sucesion :: Integer -> [Integer]
sucesion c =
map (termino c) [1..]
termino :: Integer -> Integer -> Integer
termino c 1 = 1
termino c 2 = c
termino c n = 2 * termino c (n-1) - termino c (n-2) + 2
-- 2ª solución
-- ===========
sucesion2 :: Integer -> [Integer]
sucesion2 c =
1 : c : [2*y-x+2 | (x,y) <- zip (sucesion3 c) (tail (sucesion3 c))]
-- 2ª solución
-- ===========
sucesion3 :: Integer -> [Integer]
sucesion3 c =
map (termino3 c) [1..]
termino3 :: Integer -> Integer -> Integer
termino3 c 1 = 1
termino3 c 2 = c
termino3 c n = n^2 + b*n - b
where b = c - 4
-- Comparación de eficiencia
-- =========================
-- La comparación es
-- λ> sucesion 2 !! 32
-- 1025
-- (3.95 secs, 1,991,299,256 bytes)
-- λ> sucesion2 2 !! 32
-- 1025
-- (0.01 secs, 119,856 bytes)
-- λ> sucesion3 2 !! 32
-- 1025
-- (0.01 secs, 111,176 bytes)
--
-- λ> sucesion2 2 !! (10^7)
-- 100000000000001
-- (2.26 secs, 5,200,111,128 bytes)
-- λ> sucesion3 2 !! (10^7)
-- 100000000000001
-- (0.27 secs, 1,600,111,568 bytes)
-- Comprobación de equivalencia
-- ============================
-- La propiedad es
prop_equivalencia :: Integer -> Int -> Property
prop_equivalencia c k =
c > 0 && k >= 0 ==>
take 20 (sucesion c) == take 20 (sucesion2 c) &&
sucesion2 c !! k == sucesion3 c !! k
-- La comprobación es
-- λ> quickCheck prop_equivalencia
-- +++ OK, passed 100 tests.
-- Propiedad
-- =========
-- La propiedad es
prop_sucesion :: Integer -> Int -> Property
prop_sucesion c k =
c > 0 && k >= 0 ==>
(ys !! k) `elem` xs
where xs = sucesion2 c
ys = zipWith (*) xs (tail xs)
-- La comprobación es
-- λ> quickCheck prop_sucesion
-- +++ OK, passed 100 tests.