Ir al contenido principal

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)