La serie 1 - 2 + 3 - 4 + ···
En este ejercicio se considerará la serie
1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 10 + ···
Definir las funciones
serie :: [Integer] sumaSerie :: Integer -> Integer
tales que
- serie es lalista de los términos de la serie anterior; es decir,
take 7 serie == [1,-2,3,-4,5,-6,7]
- (sumaSerie n) es la suma de los n primeros términos de la serie. Por ejemplo,
sumaSerie 5 == 3 sumaSerie 6 == -3 sumaSerie 2021 == 1011 length (show (sumaSerie (10^1000))) == 1001
Comprobar con QuickCheck que
- la suma de la serie se puede hacer tan grande como se desee; es decir, que para todo número a existe un n tal que la suma de los n primeros términos de la serie es mayor que a;
- la suma de la serie se puede hacer tan pequeña como se desee; es decir, que para todo número a existe un n tal que la suma de los n primeros términos de la serie es menor que a.
Soluciones
import Data.List (cycle, genericTake) import Test.QuickCheck (Property, (==>), quickCheck) -- 1ª definición de serie -- ====================== serie :: [Integer] serie = [(-1)^(n-1) * n | n <- [1..]] -- 2ª definición de serie -- ====================== serie2 :: [Integer] serie2 = zipWith (*) (cycle [1,-1]) [1..] -- 3ª definición de serie -- ====================== serie3 :: [Integer] serie3 = zipWith ($) (cycle [id,negate]) [1..] -- 1ª definición de sumaSerie -- ========================== sumaSerie :: Integer -> Integer sumaSerie n = sum (genericTake n serie) -- 2ª definición sumaSerie -- ======================= -- La 2ª definición se basa en la siguiente observación -- + Si n es par, entonces -- 1 - 2 + 3 - 4 + 5 - 6 + ··· + (n-1) - n -- = (1 - 2) + (3 - 4) + (5 - 6) + ··· + ((n-1) - n) -- = -1 - 1 - 1 - ··· - 1 -- = -1 * n/2 -- + Si n es impar, entonces -- 1 - 2 + 3 - 4 + 5 - 6 + ··· + (n-2) - (n-1) + n -- = (1 - 2) + (3 - 4) + (5 - 6) + ··· + ((n-2) - (n-1)) + n -- = -1 - 1 - 1 - ··· - 1 + n -- = -1 * (n-1)/2 + n -- = n - ((n-1)/2) sumaSerie2 :: Integer -> Integer sumaSerie2 n | even n = -(n `div` 2) | otherwise = n - ((n - 1) `div` 2) -- 3ª definición sumaSerie -- ======================= -- La 3ª definición se basa en la siguiente observación -- λ> [sumaSerie n | n <- [1..20]] -- [1,-1,2,-2,3,-3,4,-4,5,-5,6,-6,7,-7,8,-8,9,-9,10,-10] sumaSerie3 :: Integer -> Integer sumaSerie3 n = ((-1)^(n-1)*(2*n+1)+1) `div` 4 -- Equivalencia -- ============ -- La propiedad es prop_sumaSerie_equiv :: Integer -> Property prop_sumaSerie_equiv n = n > 0 ==> sumaSerie n == sumaSerie2 n && sumaSerie2 n == sumaSerie3 n -- La comprobación es -- λ> quickCheck prop_sumaSerie_equiv -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> sumaSerie (10^6) -- -500000 -- (3.34 secs, 5,106,633,208 bytes) -- λ> sumaSerie2 (10^6) -- -500000 -- (0.01 secs, 102,600 bytes) -- λ> sumaSerie3 (10^6) -- -500000 -- (0.02 secs, 110,976 bytes) -- λ> sumaSerie3 (10^6) -- -500000 -- Propiedad -- ========= -- La propiedad es prop_sumaSerie :: Integer -> Bool prop_sumaSerie a = any (> a) sumas && any (< a) sumas where sumas = [sumaSerie2 n | n <- [1..]] -- La comprobación es -- λ> quickCheck prop_sumaSerie -- +++ OK, passed 100 tests.