Antiimagen de función creciente
Una función f de los números naturales en los números naturales es estrictamente creciente si para cualquier par de números x, y tales que x < y se verifica que f(x) < f(y). La antiimagen por f de un número natural t es el número natural x tal que f(x) = t. No todos los números tienen antiimiagen por f, pero en caso de tenerla es única.
Definir la función
1 |
antiimagen :: (Integer -> Integer) -> Integer -> Maybe Integer |
tal que, suponiendo que f es una función creciente de los números naturales en los números naturales, (antiimagen f t) es justamente la antiimagen por f de t, si existe y es Nothing, en caso contrario. Por ejemplo,
1 2 3 4 5 6 |
antiimagen (\x -> 2*x^2-3) 47 == Just 5 antiimagen (\x -> 2*x^2-3) 48 == Nothing antiimagen (\x -> 2^x) 1024 == Just 10 antiimagen (2^) 1024 == Just 10 antiimagen (2^) (2^(10^7)) == Just 10000000 antiimagen (2^) (1+2^(10^7)) == Nothing |
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 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 |
import Data.Maybe (listToMaybe) -- 1ª solución -- =========== antiimagen :: (Integer -> Integer) -> Integer -> Maybe Integer antiimagen f t = listToMaybe [x | x <- [0..t], f x == t] -- 2ª solución -- =========== antiimagen2 :: (Integer -> Integer) -> Integer -> Maybe Integer antiimagen2 f t = busqueda (0,t) where busqueda (a,b) = listToMaybe [x | x <- [a..b], f x == t] -- 3ª solución -- =========== antiimagen3 :: (Integer -> Integer) -> Integer -> Maybe Integer antiimagen3 f t = busqueda (0,t) where busqueda (a,b) | a > b = Nothing | t < f m = busqueda (a,m-1) | t == f m = Just m | otherwise = busqueda (m+1,b) where m = (a+b) `div` 2 -- 4ª solución -- =========== antiimagen4 :: (Integer -> Integer) -> Integer -> Maybe Integer antiimagen4 f t | f x == t = Just x | otherwise = Nothing where x = busqueda (cotas f t) busqueda (a,b) = head [x | x <- [a+1..b], t <= f x] -- (cotas f t) es un par (a,b) de potencias consecutivas de 2 tal que la -- antiimagen de t por f está en el intevalo [a+1,b]. Por ejemplo, -- cotas (\x -> 2*x^2-3) 47 == (4,8) -- cotas (\x -> 2^x) 1024 == (8,16) cotas :: (Integer -> Integer) -> Integer -> (Integer, Integer) cotas f t | t <= f 0 = (-1,0) | otherwise = (b `div` 2, b) where b = until done (*2) 1 done b = t <= f b -- 5ª solución -- =========== antiimagen5 :: (Integer -> Integer) -> Integer -> Maybe Integer antiimagen5 f t | f x == t = Just x | otherwise = Nothing where x = busqueda (cotas f t) busqueda (a,b) | a+1 == b = b | t <= f m = busqueda (a,m) | otherwise = busqueda (m,b) where m = (a+b) `div` 2 -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> antiimagen (2^) (2^30) -- Just 30 -- (0.01 secs, 142,728 bytes) -- λ> antiimagen2 (2^) (2^30) -- Just 30 -- (0.01 secs, 142,784 bytes) -- λ> antiimagen3 (2^) (2^30) -- Just 30 -- (8.05 secs, 335,820,048 bytes) -- λ> antiimagen4 (2^) (2^30) -- Just 30 -- (0.01 secs, 133,984 bytes) -- λ> antiimagen5 (2^) (2^30) -- Just 30 -- (0.02 secs, 121,816 bytes) -- -- λ> antiimagen (2^) (2^50000) -- Just 50000 -- (1.29 secs, 673,789,160 bytes) -- λ> antiimagen2 (2^) (2^50000) -- Just 50000 -- (1.28 secs, 673,791,368 bytes) -- λ> antiimagen4 (2^) (2^50000) -- Just 50000 -- (0.84 secs, 342,311,360 bytes) -- λ> antiimagen5 (2^) (2^50000) -- Just 50000 -- (0.01 secs, 549,688 bytes) -- -- λ> antiimagen4 (2^) (2^100000) -- Just 100000 -- (4.37 secs, 1,210,476,848 bytes) -- λ> antiimagen5 (2^) (2^100000) -- Just 100000 -- (0.01 secs, 918,096 bytes) |
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>