Menu Close

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.
Inicial

4 soluciones de “La serie 1 – 2 + 3 – 4 + ···

  1. Rubén Muñoz Mkrtchian
    serie :: [Integer]
    serie = map aux [1..]
      where aux n | even n    = - n
                  | otherwise = n
     
    sumaSerie :: Integer -> Integer
    sumaSerie n | even n    = - n `div` 2
                | otherwise = 1 + n `div` 2
     
    propSumaGrande :: Integer -> Bool
    propSumaGrande n = not (null [x | x <- [1..], sumaSerie x > n])
     
    -- La comprobación es:
    -- λ> quickCheck propSumaGrande
    -- +++ OK, passed 100 tests.
     
    propSumaPequeña :: Integer -> Bool
    propSumaPequeña n = not (null [x | x <- [1..], sumaSerie x < n])
     
    -- La comprobación es:
    -- λ> quickCheck propSumaPequeña
    -- +++ OK, passed 100 tests.
  2. Alejandro García Alcaide
    -- SERIE
    import Test.QuickCheck
    -- Para buscar la lista que queremos, planteamos la siguiente función por
    -- comprensión con una función auxiliar, propiedad3.
    serie :: [Integer]
    serie = [propiedad3 x | x <- [1..]]
     
    -- La función propiedad3 devuelve el número sin hacerle nada si este es impar;
    -- pero, si es par, le cambia el signo.
    -- Ejemplo: propiedad3 2 = -2  || propiedad3 1 = 1
    propiedad3 :: Integer -> Integer
    propiedad3 x | even x    = -x
                 | otherwise = x
    -- Con eso, queda definida nuestra función serie. Ahora, para hallar la suma de
    -- los n primeros elementos, usaremos la función take y sum de la siguiente
    -- manera: 
    sumaSerie :: Integer -> Integer
    sumaSerie n = sum (take (fromIntegral n) serie)
     
    -- Por último, las propiedades que se deben cumplir pueden verificarse con
    -- propiedad_1 y propiedad_2, que verifican que la lista de elementos x,
    -- pertenecientes a la serie, que cumple que la suma de los x primeros elementos
    -- sea mayor o menor que un número dado no sea vacía.
     
    propiedad_1 n = not( null ([x | x <- serie, sumaSerie x > n]))
     
    propiedad_2 n = not (null ([x | x <- serie, sumaSerie x < n]))
     
    --λ> quickCheck propiedad_1
    -- OK, passed 100 tests.
    --λ> quickCheck propiedad_2
    --OK, passed 100 tests.
  3. Ángel Ruiz
    import Data.List       (genericIndex)
    import Test.QuickCheck (Positive(..),quickCheck)
     
    serie :: [Integer]
    serie = zipWith ($) (cycle [id,negate]) [1..]
     
    -- 1ª definición
    sumaSerie1 :: Integer -> Integer
    sumaSerie1 n = concatMap (x -> [x,-x]) [1..] `genericIndex` (n-1)
     
    -- 2ª definición
    sumaSerie2 :: Integer -> Integer
    sumaSerie2 n = ((-1)^(n-1) * (2*n+1) + 1) `div` 4
     
    -- Comparación de eficiencia
    -- =========================
     
    -- λ> length (show (sumaSerie1 (10^7)))
    -- 8
    -- (24.91 secs, 3,120,081,936 bytes)
    -- λ> length (show (sumaSerie2 (10^7)))
    -- 8
    -- (0.04 secs, 90,208 bytes)
    --
    -- λ> length (show (sumaSerie2 (10^1000)))
    -- 1001
    -- (0.05 secs, 2,959,384 bytes)
     
    -- Equivalencia de las soluciones
    -- ==============================
     
    -- La propiedad es
    prop_equiv :: Positive Integer -> Bool
    prop_equiv (Positive n) = sumaSerie1 n == sumaSerie2 n
     
    -- La comprobación es
    --    λ> quickCheck prop_equiv
    --    +++ OK, passed 100 tests.
     
    -- Definición
    -- ==========
     
    -- En lo que sigue usaremos la 2ª definición.
    sumaSerie :: Integer -> Integer
    sumaSerie = sumaSerie2
     
    -- Propiedades
    -- ===========
     
    -- Las propiedades son
    prop_serie1 :: Integer -> Bool
    prop_serie1 a = any ((> a) . sumaSerie) [1..]
     
    prop_serie2 :: Integer -> Bool
    prop_serie2 a = any ((< a) . sumaSerie) [1..]
     
    -- Las comprobaciones son
    --    λ> quickCheck prop_serie1
    --    +++ OK, passed 100 tests.
    --
    --    λ> quickCheck prop_serie2
    --    +++ OK, passed 100 tests.
  4. Inés Mora Caro
     
     
    -- En este ejercicio se considerará la serie:
     
    -- 1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 10 + ...
     
    serie :: [Integer]
    serie = [if odd x then x else negate x | x <- [1..]]
     
    serie' :: [Integer]
    serie' = concat [x:[negate y] | (x,y) <- zip [1,3..] [2,4..]]
     
    -- Comparamos su eficiencia y deducimos que la función serie es más
    -- impaciente y ocupa menos memoria pero la función serie' tarda menos
    -- tiempo en calcular.
     
    -- λ> last $ take 1000000 serie
    -- -1000000
    -- (0.87 secs, 240,059,288 bytes)
     
    -- λ> last $ take 1000000 serie'
    -- -1000000
    -- (0.77 secs, 344,063,864 bytes)
     
     
    -- (sumaSerie n) es la suma de los n primeros términos de la serie.
    sumaSerie :: Integer -> Integer
    sumaSerie n = sum (genericTake n serie)
     
     
    --Comprobar con QuickCheck que:
     
    -- 1) 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.
     
    -- 2) 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.
     
    -- 1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 10 + ...
     
    -- sumaSerie n = last [1,-1,2,-2,3,-3..]
     
    -- Para hacer la función más genérica, vemos primero cada caso particular.
    -- prop_sumaSerieMayor' :: Integer -> Bool
    -- prop_sumaSerieMayor' n | n == 0 = n < sumaSerie 1
    --                        | n > 0 && even n = (n < sumaSerie (2*n+1))
    --                        | n < 0 && even n = (n < sumaSerie (2*(abs n)+1))
    --                        | n > 0 && odd n  = (n < sumaSerie (2*n+1))
    --                        | n < 0 && odd n  = (n < sumaSerie (2*(abs n)+1))
     
    -- 1)
    prop_sumaSerieMayor :: Integer -> Bool
    prop_sumaSerieMayor n = n < sumaSerie (2*(abs n)+1)
     
    -- λ> quickCheck prop_sumaSerieMayor
    -- +++ OK, passed 100 tests.
     
    -- 2)
    prop_sumaSerieMenor :: Integer -> Bool
    prop_sumaSerieMenor n = n > sumaSerie (2*(abs n)+2)
     
    -- λ> quickCheck prop_sumaSerieMenor
    -- +++ OK, passed 100 tests.
     
    -- En general,
    prop_sumaSerie :: Integer -> Bool
    prop_sumaSerie n = prop_sumaSerieMayor n == prop_sumaSerieMenor n
     
    -- λ> quickCheck prop_sumaSerie
    -- +++ OK, passed 100 tests.

Leave a Reply to Alejandro García Alcaide Cancel reply

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.