Los números armónicos no son enteros
Los números armónicos son las sumas de los inversos de de los primeros números enteros positivos; es decir, el n-ésimo número armónico es
1 |
H(n) = 1 + 1/2 + 1/3 + ··· + 1/n |
Los primeros números armónicos son
1 |
1, 3/2, 11/6, 25/12, 137/60, .. |
Definir, usando la librería de los números racionales (Data.Ratio), las funciones
1 2 3 |
armonico :: Integer -> Rational armonicos :: [Rational] esEntero :: Rational -> Bool |
tales que
- (armonico n) es el n-ésimo número armónico. Por ejemplo,
1 2 3 4 |
armonico 2 == 3 % 2 armonico 3 == 11 % 6 armonico 4 == 25 % 12 armonico 5 == 137 % 60 |
- armonicos es la lista de los números armónicos. Por ejemplo,
1 |
take 5 armonicos == [1 % 1,3 % 2,11 % 6,25 % 12,137 % 60] |
- (esEntero x) se verifica si x es un número entero. Por ejemplo,
1 2 |
esEntero (1 % 7) == False esEntero (1 % 7 + 20 % 7) == True |
Comprobar con QuickCheck que
- nigún número armónico, excepto el primero, es un número entero y
-
la diferencia de dos números armónicos distintos nunca es un número entero.
Nota: Este ejercicio está basado en el artículo Sums of consecutive reciprocals publicado por John D. Cook en su blog el 23 de enero de 2021.
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 |
import Data.List (genericIndex) import Data.Ratio ((%), denominator) import Test.QuickCheck (Property, (==>), quickCheck) -- 1ª solución -- =========== armonico :: Integer -> Rational armonico 1 = 1 armonico n = 1 % n + armonico (n-1) armonicos :: [Rational] armonicos = map armonico [1..] esEntero :: Rational -> Bool esEntero x = denominator x == 1 -- 2ª solución -- =========== armonicos2 :: [Rational] armonicos2 = scanl1 (\ x y -> x + y) [1 % n | n <- [1..]] armonico2 :: Integer -> Rational armonico2 n = armonicos `genericIndex` n -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> fromRational (armonicos !! (10^4)) -- 9.787706026045383 -- (9.17 secs, 29,293,137,856 bytes) -- λ> fromRational (armonicos2 !! (10^4)) -- 9.787706026045383 -- (9.42 secs, 29,292,225,904 bytes) -- Propiedades -- =========== -- La 1ª propiedad es prop_armonicos :: Integer -> Property prop_armonicos n = n > 1 ==> not (esEntero (armonico n)) -- La comprobación de la 1ª propiedad es -- λ> quickCheck prop_armonicos -- +++ OK, passed 100 tests. -- La 2ª propiedad es prop_armonicos2 :: Integer -> Integer -> Property prop_armonicos2 n m = n > 0 && m > 0 && n /= m ==> not (esEntero (armonico n - armonico m)) -- La comprobación de la segunda propiedad es -- λ> quickCheck prop_armonicos2 -- +++ OK, passed 100 tests. |
Nuevas soluciones
- En los comentarios se pueden escribir nuevas soluciones.
- El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>
4 Comentarios