Suma de los dígitos de un número
Definir la función
1 |
sumaDigitos :: Integer -> Integer |
tal que sumaDigitos n
es la suma de los dígitos de n
. Por ejemplo,
1 2 3 |
sumaDigitos 3 == 3 sumaDigitos 2454 == 15 sumaDigitos 20045 == 11 |
Soluciones
A continuación se muestran las soluciones en Haskell y las soluciones en Python.
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 |
import Data.List (foldl') import Test.QuickCheck -- 1ª solución -- =========== sumaDigitos1 :: Integer -> Integer sumaDigitos1 n = sum (digitos n) -- (digitos n) es la lista de los dígitos del número n. Por ejemplo, -- digitos 320274 == [3,2,0,2,7,4] digitos :: Integer -> [Integer] digitos n = [read [x] | x <- show n] -- Nota. En lugar de la definición anterior de digitos se puede usar -- cualquiera del ejercicio "Dígitos de un número" https://bit.ly/3Tkhc2T -- 2ª solución -- =========== sumaDigitos2 :: Integer -> Integer sumaDigitos2 n = foldl' (+) 0 (digitos n) -- 3ª solución -- =========== sumaDigitos3 :: Integer -> Integer sumaDigitos3 n | n < 10 = n | otherwise = n `rem` 10 + sumaDigitos3 (n `div` 10) -- 4ª solución -- =========== sumaDigitos4 :: Integer -> Integer sumaDigitos4 = aux 0 where aux r n | n < 10 = r + n | otherwise = aux (r + n `rem` 10) (n `div` 10) -- Comprobación de equivalencia -- ============================ -- La propiedad es prop_sumaDigitos :: NonNegative Integer -> Bool prop_sumaDigitos (NonNegative n) = all (== sumaDigitos1 n) [sumaDigitos2 n, sumaDigitos3 n, sumaDigitos4 n] -- La comprobación es -- λ> quickCheck prop_sumaDigitos -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> sumaDigitos1 (product [1..2*10^4]) -- 325494 -- (0.64 secs, 665,965,832 bytes) -- λ> sumaDigitos2 (product [1..2*10^4]) -- 325494 -- (0.41 secs, 660,579,064 bytes) -- λ> sumaDigitos3 (product [1..2*10^4]) -- 325494 -- (1.58 secs, 1,647,082,224 bytes) -- λ> sumaDigitos4 (product [1..2*10^4]) -- 325494 -- (1.72 secs, 1,662,177,792 bytes) -- -- λ> sumaDigitos1 (product [1..5*10^4]) -- 903555 -- (2.51 secs, 3,411,722,136 bytes) -- λ> sumaDigitos2 (product [1..5*10^4]) -- 903555 -- (2.30 secs, 3,396,802,856 bytes) |
El código se encuentra en GitHub.
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
from functools import reduce from math import factorial from operator import add from sys import setrecursionlimit from timeit import Timer, default_timer from hypothesis import given from hypothesis import strategies as st setrecursionlimit(10**6) # 1ª solución # =========== # digitos(n) es la lista de los dígitos del número n. Por ejemplo, # digitos(320274) == [3, 2, 0, 2, 7, 4] def digitos(n: int) -> list[int]: return list(map(int, list(str(n)))) def sumaDigitos1(n: int) -> int: return sum(digitos(n)) # Nota. En lugar de la definición anterior de digitos se puede usar # cualquiera del ejercicio "Dígitos de un número" https://bit.ly/3Tkhc2T # 2ª solución # =========== def sumaDigitos2(n: int) -> int: return reduce(add, digitos(n)) # 3ª solución # =========== def sumaDigitos3(n: int) -> int: if n < 10: return n return n % 10 + sumaDigitos3(n // 10) # 4ª solución # =========== def sumaDigitos4(n: int) -> int: def aux(r: int, m: int) -> int: if m < 10: return r + m return aux(r + m % 10, m // 10) return aux(0, n) # 5ª solución # =========== def sumaDigitos5(n: int) -> int: r = 0 for x in digitos(n): r = r + x return r # Comprobación de equivalencia # ============================ # La propiedad es @given(st.integers(min_value=0, max_value=1000)) def test_sumaDigitos(n: int) -> None: r = sumaDigitos1(n) assert sumaDigitos2(n) == r assert sumaDigitos3(n) == r assert sumaDigitos4(n) == r assert sumaDigitos5(n) == r # La comprobación es # src> poetry run pytest -q suma_de_los_digitos_de_un_numero.py # 1 passed in 0.35s # Comparación de eficiencia # ========================= def tiempo(e: str) -> None: """Tiempo (en segundos) de evaluar la expresión e.""" t = Timer(e, "", default_timer, globals()).timeit(1) print(f"{t:0.2f} segundos") # La comparación es # >>> tiempo('sumaDigitos1(factorial(6*10**3))') # 0.01 segundos # >>> tiempo('sumaDigitos2(factorial(6*10**3))') # 0.01 segundos # >>> tiempo('sumaDigitos3(factorial(6*10**3))') # 0.13 segundos # >>> tiempo('sumaDigitos4(factorial(6*10**3))') # 0.13 segundos # >>> tiempo('sumaDigitos5(factorial(6*10**3))') # 0.01 segundos # # >>> tiempo('sumaDigitos1(factorial(10**5))') # 2.20 segundos # >>> tiempo('sumaDigitos2(factorial(10**5))') # 2.22 segundos # >>> tiempo('sumaDigitos5(factorial(10**5))') # 2.19 segundos |
El código se encuentra en GitHub