Exponentes de Hamming
Los números de Hamming forman una sucesión estrictamente creciente de números que cumplen las siguientes condiciones:
- El número 1 está en la sucesión.
- Si x está en la sucesión, entonces 2x, 3x y 5x también están.
- Ningún otro número está en la sucesión.
Los primeros números de Hamming son 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, ...
Los exponentes de un número de Hamming n es una terna (x,y,z) tal que n = 2^x*3^y*5^z
. Por ejemplo, los exponentes de 600 son (3,1,2) ya que 600 = 2^x*3^1*5^z
.
Definir la sucesión
sucExponentesHamming :: [(Int,Int,Int)]
cuyos elementos son los exponentes de los números de Hamming. Por ejemplo,
λ> take 20 sucExponentesHamming [(0,0,0),(1,0,0),(0,1,0),(2,0,0),(0,0,1),(1,1,0),(3,0,0), (0,2,0),(1,0,1),(2,1,0),(0,1,1),(4,0,0),(1,2,0),(2,0,1), (3,1,0),(0,0,2),(0,3,0),(1,1,1),(5,0,0),(2,2,0),(3,0,1)] λ> sucExponentesHamming !! (5*10^5) (74,82,7)
Soluciones
import Data.Numbers.Primes (primeFactors) sucExponentesHamming :: [(Int,Int,Int)] sucExponentesHamming = map exponentes hamming -- (exponentes n) es la terna de exponentes del número de Hamming n. Por -- ejemplo, -- exponentes 600 == (3,1,2) exponentes :: Integer -> (Int,Int,Int) exponentes x = (length as, length cs, length ds) where xs = primeFactors x (as,bs) = span (==2) xs (cs,ds) = span (==3) bs -- hamming es la sucesión de los números de Hamming. Por ejemplo, -- λ> take 21 hamming -- [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40] hamming :: [Integer] hamming = 1 : mezcla3 [2*i | i <- hamming] [3*i | i <- hamming] [5*i | i <- hamming] -- mezcla3 xs ys zs es la lista obtenida mezclando las listas ordenadas -- xs, ys y zs y eliminando los elementos duplicados. Por ejemplo, -- mezcla3 [2,4,6,8,10] [3,6,9,12] [5,10] == [2,3,4,5,6,8,9,10,12] mezcla3 :: Ord a => [a] -> [a] -> [a] -> [a] mezcla3 xs ys zs = mezcla2 xs (mezcla2 ys zs) -- mezcla2 xs ys zs es la lista obtenida mezclando las listas ordenadas -- xs e ys y eliminando los elementos duplicados. Por ejemplo, -- mezcla2 [2,4,6,8,10,12] [3,6,9,12] == [2,3,4,6,8,9,10,12] mezcla2 :: Ord a => [a] -> [a] -> [a] mezcla2 p@(x:xs) q@(y:ys) | x < y = x:mezcla2 xs q | x > y = y:mezcla2 p ys | otherwise = x:mezcla2 xs ys mezcla2 [] ys = ys mezcla2 xs [] = xs