Número a partir de sus dígitos
Definir la función
1 |
listaNumero :: [Integer] -> Integer |
tal que listaNumero xs
es el número formado por los dígitos xs
. Por ejemplo,
1 2 3 |
listaNumero [5] == 5 listaNumero [1,3,4,7] == 1347 listaNumero [0,0,1] == 1 |
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
import Data.List (foldl') import Data.Digits (unDigits) import Test.QuickCheck -- 1ª solución -- =========== listaNumero1 :: [Integer] -> Integer listaNumero1 = aux . reverse where aux :: [Integer] -> Integer aux [] = 0 aux (x:xs) = x + 10 * aux xs -- 2ª solución -- =========== listaNumero2 :: [Integer] -> Integer listaNumero2 = aux 0 where aux :: Integer -> [Integer] -> Integer aux r [] = r aux r (x:xs) = aux (x+10*r) xs -- 3ª solución -- =========== listaNumero3 :: [Integer] -> Integer listaNumero3 = aux 0 where aux :: Integer -> [Integer] -> Integer aux = foldl (\ r x -> x + 10 * r) -- 4ª solución -- =========== listaNumero4 :: [Integer] -> Integer listaNumero4 = foldl' (\ r x -> x + 10 * r) 0 -- 5ª solución -- =========== listaNumero5 :: [Integer] -> Integer listaNumero5 xs = sum [y*10^n | (y,n) <- zip (reverse xs) [0..]] -- 6ª solución -- =========== listaNumero6 :: [Integer] -> Integer listaNumero6 xs = sum (zipWith (\ y n -> y*10^n) (reverse xs) [0..]) -- 7ª solución -- =========== listaNumero7 :: [Integer] -> Integer listaNumero7 = unDigits 10 -- 7ª solución -- =========== listaNumero8 :: [Integer] -> Integer listaNumero8 = read . concatMap show -- Comprobación de equivalencia -- ============================ -- La propiedad es prop_listaNumero :: NonEmptyList Integer -> Bool prop_listaNumero (NonEmpty xs) = all (== listaNumero1 ys) [listaNumero2 ys, listaNumero3 ys, listaNumero4 ys, listaNumero5 ys, listaNumero6 ys, listaNumero7 ys, listaNumero8 ys] where ys = map (`mod` 10) xs -- La comprobación es -- λ> quickCheck prop_listaNumero -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> length (show (listaNumero1 (replicate (10^5) 9))) -- 100000 -- (4.01 secs, 4,309,740,064 bytes) -- λ> length (show (listaNumero2 (replicate (10^5) 9))) -- 100000 -- (4.04 secs, 4,307,268,856 bytes) -- λ> length (show (listaNumero3 (replicate (10^5) 9))) -- 100000 -- (4.08 secs, 4,300,868,816 bytes) -- λ> length (show (listaNumero4 (replicate (10^5) 9))) -- 100000 -- (0.42 secs, 4,288,480,208 bytes) -- λ> length (show (listaNumero4 (replicate (10^5) 9))) -- 100000 -- (0.41 secs, 4,288,480,208 bytes) -- λ> length (show (listaNumero5 (replicate (10^5) 9))) -- 100000 -- (43.35 secs, 10,702,827,328 bytes) -- λ> length (show (listaNumero6 (replicate (10^5) 9))) -- 100000 -- (46.89 secs, 10,693,227,280 bytes) -- λ> length (show (listaNumero7 (replicate (10^5) 9))) -- 100000 -- (4.33 secs, 4,297,499,344 bytes) -- λ> length (show (listaNumero8 (replicate (10^5) 9))) -- 100000 -- (0.03 secs, 60,760,360 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 101 102 |
from functools import reduce 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 # =========== def listaNumero1(xs: list[int]) -> int: def aux(ys: list[int]) -> int: if ys: return ys[0] + 10 * aux(ys[1:]) return 0 return aux(list(reversed(xs))) # 2ª solución # =========== def listaNumero2(xs: list[int]) -> int: def aux(r: int, ys: list[int]) -> int: if ys: return aux(ys[0] + 10 * r, ys[1:]) return r return aux(0, xs) # 3ª solución # =========== def listaNumero3(xs: list[int]) -> int: return reduce((lambda r, x: x + 10 * r), xs) # 4ª solución # =========== def listaNumero4(xs: list[int]) -> int: r = 0 for x in xs: r = x + 10 * r return r # 5ª solución # =========== def listaNumero5(xs: list[int]) -> int: return sum((y * 10**n for (y, n) in zip(list(reversed(xs)), range(0, len(xs))))) # 6ª solución # =========== def listaNumero6(xs: list[int]) -> int: return int("".join(list(map(str, xs)))) # Comprobación de equivalencia # ============================ # La propiedad es @given(st.lists(st.integers(min_value=0, max_value=9), min_size=1)) def test_listaNumero(xs: list[int]) -> None: r = listaNumero1(xs) assert listaNumero2(xs) == r assert listaNumero3(xs) == r assert listaNumero4(xs) == r assert listaNumero5(xs) == r assert listaNumero6(xs) == r # La comprobación es # src> poetry run pytest -q numero_a_partir_de_sus_digitos.py # 1 passed in 0.27s # 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('listaNumero1([9]*(10**4))') # 0.28 segundos # >>> tiempo('listaNumero2([9]*(10**4))') # 0.16 segundos # >>> tiempo('listaNumero3([9]*(10**4))') # 0.01 segundos # >>> tiempo('listaNumero4([9]*(10**4))') # 0.01 segundos # >>> tiempo('listaNumero5([9]*(10**4))') # 0.41 segundos # >>> tiempo('listaNumero6([9]*(10**4))') # 0.00 segundos # # >>> tiempo('listaNumero3([9]*(2*10**5))') # 3.45 segundos # >>> tiempo('listaNumero4([9]*(2*10**5))') # 3.29 segundos # >>> tiempo('listaNumero6([9]*(2*10**5))') # 0.19 segundos |
El código se encuentra en GitHub.