Reconocimiento de potencias de 2
Definir la función
esPotenciaDeDos :: Integer -> Bool
tal que (esPotenciaDeDos n) se verifica si n es una potencia de dos (suponiendo que n es mayor que 0). Por ejemplo.
esPotenciaDeDos 1 == True esPotenciaDeDos 2 == True esPotenciaDeDos 6 == False esPotenciaDeDos 8 == True esPotenciaDeDos 1024 == True esPotenciaDeDos 1026 == False esPotenciaDeDos (2^100000) == True
Nota: Comprobar la definición para grandes potencias de 2.
Soluciones
import Data.Bits ((.&.)) -- 1ª definición -- ============= esPotenciaDeDos1 :: Integer -> Bool esPotenciaDeDos1 n | n <= 2 = True | n `mod` 2 == 0 = esPotenciaDeDos1 (n `div` 2) | otherwise = False -- 2ª definición -- ============= esPotenciaDeDos2 :: Integer -> Bool esPotenciaDeDos2 n = n == head (dropWhile (<n) potenciasDeDos) -- potenciasDeDos es la lista de las potencias de dos. Por ejemplo, potenciasDeDos :: [Integer] potenciasDeDos = iterate (*2) 1 -- 3ª definición -- ============= -- Usando la función (.&.) de la librería Data.Bits. Dicha función -- calcula el número correspondiente a la conjunción de las -- representaciones binarias de sus argumentos. Por ejemplo, -- 6 .&. 3 == 2 -- ya que -- la representación binaria de 6 es [1,1,0] -- la representación binaria de 3 es [1,1] -- la conjunción es [1,0] -- la representación decimal de [1,0] es 2 -- -- Otros ejemplos: -- 4 .&. 3 == [1,0,0] .&. [1,1] == 0 -- 8 .&. 7 == [1,0,0,0] .&. [1,1,1] = 0 esPotenciaDeDos3 :: Integer -> Bool esPotenciaDeDos3 n = n .&. (n-1) == 0 -- --------------------------------------------------------------------- -- § Comparación de eficiencia -- -- --------------------------------------------------------------------- -- λ> esPotenciaDeDos1 (2^100000) -- True -- (2.02 secs, 667452136 bytes) -- -- λ> esPotenciaDeDos2 (2^100000) -- True -- (1.29 secs, 647987408 bytes) -- -- λ> esPotenciaDeDos3 (2^100000) -- True -- (0.01 secs, 2062528 bytes)