Sucesiones conteniendo al producto de consecutivos
El enunciado de un problema para la IMO (Olimpiada Internacional de Matemáticas) de 1984 es
Sea c un entero positivo. La sucesión f(n) está definida por
f(1) = 1, f(2) = c, f(n+1) = 2f(n) – f(n-1) + 2 (n ≥ 2).
Demostrar que para cada k ∈ N exist un r ∈ N tal que f(k)f(k+1) = f(r).
Definir la función
| 1 |    sucesion :: Integer -> [Integer] | 
tal que los elementos de (sucesion c) son los términos de la suceción f(n) definida en el enunciado del problema. Por ejemplo,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |    take 7 (sucesion 2)   ==  [1,2,5,10,17,26,37]    take 7 (sucesion 3)   ==  [1,3,7,13,21,31,43]    take 7 (sucesion 4)   ==  [1,4,9,16,25,36,49]    sucesion 2 !! 30      ==  901    sucesion 3 !! 30      ==  931    sucesion 4 !! 30      ==  961    sucesion 2 !! (10^2)  ==  10001    sucesion 2 !! (10^3)  ==  1000001    sucesion 2 !! (10^4)  ==  100000001    sucesion 2 !! (10^5)  ==  10000000001    sucesion 2 !! (10^6)  ==  1000000000001    sucesion 2 !! (10^7)  ==  100000000000001    sucesion 3 !! (10^7)  ==  100000010000001    sucesion 4 !! (10^7)  ==  100000020000001    sucesion 2 !! (10^8)  ==  10000000000000001    sucesion 3 !! (10^8)  ==  10000000100000001    sucesion 4 !! (10^8)  ==  10000000200000001    sucesion 2 !! (10^9)  ==  1000000000000000001 | 
Comprobar con QuickCheck que para cada k ∈ N existe un r ∈ N tal que f(k)f(k+1) = f(r).
Soluciones
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 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. | 
En los comentarios se pueden escribir otras soluciones, escribiendo el código entre una línea con <pre lang="haskell"> y otra con </pre>