Número a partir de sus dígitos
Definir la función
listaNumero :: [Integer] -> Integer
tal que listaNumero xs
es el número formado por los dígitos xs
. Por ejemplo,
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.
Soluciones en Haskell
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.
Soluciones en Python
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.