Sucesión de Lichtenberg
La sucesión de Lichtenberg esta formada por la representación decimal de los números binarios de la sucesión de dígitos 0 y 1 alternados. Los primeros términos de ambas sucesiones son
Alternada ..... Lichtenberg 0 ....................... 0 1 ....................... 1 10 ...................... 2 101 ..................... 5 1010 ................... 10 10101 .................. 21 101010 ................. 42 1010101 ................ 85 10101010 .............. 170 101010101 ............. 341 1010101010 ............ 682 10101010101 .......... 1365 101010101010 ......... 2730
Definir las funciones
lichtenberg :: [Integer] graficaLichtenberg :: Int -> IO ()
tales que
- lichtenberg es la lista cuyos elementos son los términos de la sucesión de Lichtenberg. Por ejemplo,
λ> take 17 lichtenberg [0,1,2,5,10,21,42,85,170,341,682,1365,2730,5461,10922,21845,43690]
- (graficaLichtenberg n) dibuja la gráfica del número de dígitos de los n primeros términos de la sucesión de Lichtenberg. Por ejemlo, (graficaLichtenberg 100) dibuja
Comprobar con QuickCheck que todos los términos de la sucesión de Lichtenberg, a partir del 4º, son números compuestos.
Soluciones
import Data.Char (digitToInt) import Graphics.Gnuplot.Simple import Test.QuickCheck import Data.Numbers.Primes (isPrime) -- 1ª solución -- =========== lichtenberg1 :: [Integer] lichtenberg1 = map binarioAdecimal sucAlternada -- sucAlternada es la lista cuyos elementos son los términos de la -- sucesión de los dígitos 0 y 1 alternados. Por ejemplo, -- λ> take 7 sucAlternada -- ["0","1","10","101","1010","10101","101010"] sucAlternada :: [String] sucAlternada = ['0'] : [take n cadenaAlternada | n <- [1..]] -- cadenaAltenada es la cadena formada alternando los caracteres 1 y -- 0. Por ejemplo, -- take 20 cadenaAlternada == "10101010101010101010" cadenaAlternada :: String cadenaAlternada = cycle ['1','0'] -- (binarioAdecimal cs) es el número decimal correspondiente al número -- binario cuya cadena de dígitos es cs. Por ejemplo, -- binarioAdecimal "11101" == 29 binarioAdecimal :: String -> Integer binarioAdecimal = foldl (\acc x -> acc * 2 + (toInteger . digitToInt) x) 0 -- 2ª solución lichtenberg2 :: [Integer] lichtenberg2 = map a [0..] where a 0 = 0 a 1 = 1 a n = a (n-1) + 2 * a (n-2) + 1 -- 3ª solución lichtenberg3 :: [Integer] lichtenberg3 = 0 : 1 : map (+1) (zipWith (+) (tail lichtenberg3) (map (*2) lichtenberg3)) -- Comprobación de eficiencia -- λ> length (show (lichtenberg1 !! 27)) -- 8 -- (0.02 secs, 155,384 bytes) -- λ> length (show (lichtenberg2 !! 27)) -- 8 -- (2.22 secs, 311,157,760 bytes) -- -- λ> length (show (lichtenberg1 !! (8*10^4))) -- 24083 -- (1.28 secs, 664,207,040 bytes) -- λ> length (show (lichtenberg3 !! (8*10^4))) -- 24083 -- (2.59 secs, 1,253,328,200 bytes) -- La propiedad es propLichtenberg :: Int -> Property propLichtenberg n = n > 4 ==> not (isPrime (lichtenberg1 !! n)) -- La comprobación es -- λ> quickCheck propLichtenberg -- +++ OK, passed 100 tests. graficaLichtenberg :: Int -> IO () graficaLichtenberg n = plotList [ Key Nothing , Title "Numero de digitos de la sucesion de Lichtenberg" , PNG "Sucesion_de_Lichtenberg.png" ] (take n (map (length . show) lichtenberg1))