tal que (division cs) es la lista de las palabras formadas por dos elementos consecutivos de cs y, en el caso de que la longitud de cs sea impar, el último elemento de la última palabra es el carácter de subrayado. Por ejemplo,
Se pueden escribir otras soluciones en los comentarios.
El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>
Pensamiento
«Las matemáticas tienen un triple objetivo. Debe proporcionar un instrumento para el estudio de la naturaleza. Pero esto no es todo: tiene un objetivo filosófico y, me atrevo a decir, un objetivo estético.»
se pueden calcular el número pi con la precisión que se desee. Por ejemplo,
λ> import Data.Number.CReal
λ> showCReal 60 pi
"3.141592653589793238462643383279502884197169399375105820974945"
λ> import Data.Number.CReal
λ> showCReal 60 pi
"3.141592653589793238462643383279502884197169399375105820974945"
importa la librería y calcula el número pi con 60 decimales.
La distribución de las diferencias de los dígitos consecutivos para los 18 primeros n dígitos de pi se calcula como sigue: los primeros 18 dígitos de pi son
(graficas ns f) dibuja en el fichero f las gráficas de las distribuciones de las diferencias de los dígitos consecutivos para los primeros n dígitos de pi, para n en ns. Por ejemplo, al evaluar (graficas [100,250..4000] «distribucionDDCpi.png» se escribe en el fichero «distribucionDDCpi.png» la siguiente gráfica
Soluciones
import Data.Number.CReal
import Graphics.Gnuplot.Simple
import Data.Array
-- λ> digitosPi 18-- [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3]
digitosPi ::Int->[Int]
digitosPi n =init[read[c]| c <-(x:xs)]where(x:_:xs)= showCReal n pi-- λ> diferenciasConsecutivos (digitosPi 18)-- [2,-3,3,-4,-4,7,-4,1,2,-2,-3,-1,2,-2,6,1,-1]
diferenciasConsecutivos ::Num a =>[a]->[a]
diferenciasConsecutivos xs =zipWith(-) xs (tail xs)
distribucionDDCpi ::Int->[Int]
distribucionDDCpi =
distribucion . diferenciasConsecutivos . digitosPi
where distribucion xs =
elems (accumArray (+)0(-9,9)(zip xs (repeat1)))
graficas ::[Int]-> FilePath ->IO()
graficas ns f =
plotLists [Key Nothing, PNG f][puntos n | n <- ns]where puntos ::Int->[(Int,Int)]
puntos n =zip[-9..9](distribucionDDCpi n)
import Data.Number.CReal
import Graphics.Gnuplot.Simple
import Data.Array
-- λ> digitosPi 18
-- [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3]
digitosPi :: Int -> [Int]
digitosPi n = init [read [c] | c <- (x:xs)]
where (x:_:xs) = showCReal n pi
-- λ> diferenciasConsecutivos (digitosPi 18)
-- [2,-3,3,-4,-4,7,-4,1,2,-2,-3,-1,2,-2,6,1,-1]
diferenciasConsecutivos :: Num a => [a] -> [a]
diferenciasConsecutivos xs =
zipWith (-) xs (tail xs)
distribucionDDCpi :: Int -> [Int]
distribucionDDCpi =
distribucion . diferenciasConsecutivos . digitosPi
where distribucion xs =
elems (accumArray (+) 0 (-9,9) (zip xs (repeat 1)))
graficas :: [Int] -> FilePath -> IO ()
graficas ns f =
plotLists [Key Nothing, PNG f]
[puntos n | n <- ns]
where puntos :: Int -> [(Int,Int)]
puntos n = zip [-9..9] (distribucionDDCpi n)
Pensamiento
Doy consejo, a fuer de viejo:
nunca sigas mi consejo.
ej1, ej2, ej3 :: Arbol Int
ej1 = N (-1) [N 2 [N 4 [], N 5 []], N 3 []]
ej2 = N 1 [N (-2) [N (-4) []], N 3 []]
ej3 = N 1 [N (-2) [N 4 [], N 5 []], N 7 [], N 3 []]
ej1, ej2, ej3 :: Arbol Int
ej1 = N (-1) [N 2 [N 4 [], N 5 []], N 3 []]
ej2 = N 1 [N (-2) [N (-4) []], N 3 []]
ej3 = N 1 [N (-2) [N 4 [], N 5 []], N 7 [], N 3 []]
Definir la función
todasDesdeAlguno :: (a -> Bool) -> Arbol a -> Bool
todasDesdeAlguno :: (a -> Bool) -> Arbol a -> Bool
tal que (todasDesdeAlguno p ar) se verifica si para toda rama existe un elemento a partir del cual todos los elementos de la rama verifican la propiedad p. Por ejemplo,
import Data.List (tails)data Arbol a = N a [Arbol a]derivingShow
ej1, ej2, ej3 :: Arbol Int
ej1 = N (-1)[N 2[N 4[], N 5[]], N 3[]]
ej2 = N 1[N (-2)[N (-4)[]], N 3[]]
ej3 = N 1[N (-2)[N 4[], N 5[]], N 7[], N 3[]]-- 1ª solución-- ===========
todasDesdeAlguno ::(b ->Bool)-> Arbol b ->Bool
todasDesdeAlguno p a =all(desdeAlguno p)(ramas a)-- (desdeAlguno p xs) se verifica si la propiedad xs tiene un elementemo-- a partir del cual todos los siguientes cumplen la propiedad p. Por-- ejemplo, -- desdeAlguno (>0) [-1,2,4] == True-- desdeAlguno (>0) [1,-2,-4] == False-- desdeAlguno (>0) [1,-2,4] == True-- 1ª definición de desdeAlguno
desdeAlguno1 ::(a ->Bool)->[a]->Bool
desdeAlguno1 p xs =not(null(takeWhile p (reverse xs)))-- 2ª definición de desdeAlguno
desdeAlguno2 ::(a ->Bool)->[a]->Bool
desdeAlguno2 p xs =any(all p)(init(tails xs))-- Comparación de eficiencia:-- λ> desdeAlguno1 (>10^7) [1..1+10^7]-- True-- (4.36 secs, 960,101,896 bytes)-- λ> desdeAlguno2 (>10^7) [1..1+10^7]-- True-- (5.62 secs, 3,600,101,424 bytes)-- Usaremos la 1ª definición de desdeAlguno
desdeAlguno ::(a ->Bool)->[a]->Bool
desdeAlguno = desdeAlguno1
-- (ramas a) es la lista de las ramas de a. Por ejemplo,-- ramas ej1 == [[-1,2,4],[-1,2,5],[-1,3]]-- ramas ej2 == [[1,-2,-4],[1,3]]-- ramas ej3 == [[1,-2,4],[1,-2,5],[1,7],[1,3]]
ramas :: Arbol a ->[[a]]
ramas (N x [])=[[x]]
ramas (N x as)=map(x:)(concatMap ramas as)-- 2ª solución-- ===========
todasDesdeAlguno2 ::(b ->Bool)-> Arbol b ->Bool
todasDesdeAlguno2 p (N x [])= p x
todasDesdeAlguno2 p (N _ as)=all(todasDesdeAlguno2 p)as
import Data.List (tails)
data Arbol a = N a [Arbol a]
deriving Show
ej1, ej2, ej3 :: Arbol Int
ej1 = N (-1) [N 2 [N 4 [], N 5 []], N 3 []]
ej2 = N 1 [N (-2) [N (-4) []], N 3 []]
ej3 = N 1 [N (-2) [N 4 [], N 5 []], N 7 [], N 3 []]
-- 1ª solución
-- ===========
todasDesdeAlguno :: (b -> Bool) -> Arbol b -> Bool
todasDesdeAlguno p a = all (desdeAlguno p) (ramas a)
-- (desdeAlguno p xs) se verifica si la propiedad xs tiene un elementemo
-- a partir del cual todos los siguientes cumplen la propiedad p. Por
-- ejemplo,
-- desdeAlguno (>0) [-1,2,4] == True
-- desdeAlguno (>0) [1,-2,-4] == False
-- desdeAlguno (>0) [1,-2,4] == True
-- 1ª definición de desdeAlguno
desdeAlguno1 :: (a -> Bool) -> [a] -> Bool
desdeAlguno1 p xs =
not (null (takeWhile p (reverse xs)))
-- 2ª definición de desdeAlguno
desdeAlguno2 :: (a -> Bool) -> [a] -> Bool
desdeAlguno2 p xs = any (all p) (init (tails xs))
-- Comparación de eficiencia:
-- λ> desdeAlguno1 (>10^7) [1..1+10^7]
-- True
-- (4.36 secs, 960,101,896 bytes)
-- λ> desdeAlguno2 (>10^7) [1..1+10^7]
-- True
-- (5.62 secs, 3,600,101,424 bytes)
-- Usaremos la 1ª definición de desdeAlguno
desdeAlguno :: (a -> Bool) -> [a] -> Bool
desdeAlguno = desdeAlguno1
-- (ramas a) es la lista de las ramas de a. Por ejemplo,
-- ramas ej1 == [[-1,2,4],[-1,2,5],[-1,3]]
-- ramas ej2 == [[1,-2,-4],[1,3]]
-- ramas ej3 == [[1,-2,4],[1,-2,5],[1,7],[1,3]]
ramas :: Arbol a -> [[a]]
ramas (N x []) = [[x]]
ramas (N x as) = map (x:) (concatMap ramas as)
-- 2ª solución
-- ===========
todasDesdeAlguno2 :: (b -> Bool) -> Arbol b -> Bool
todasDesdeAlguno2 p (N x []) = p x
todasDesdeAlguno2 p (N _ as) = all (todasDesdeAlguno2 p) as
Pensamiento
Por dar al viento trabajo,
cosía con hilo doble
las hojas secas del árbol.
El orden de los elementos es desde la raíz hasta el extremo inferior izquierdo desde él hasta el inferior derecho y desde él hasta la raíz.
Soluciones
data Arbol = H Int| N Int Arbol Arbol
derivingShow
ejArbol1, ejArbol2, ejArbol3 :: Arbol
ejArbol1 = N 3(N 2(N 5(H 1)(H 4))(H 7))(N 8(H 6)(H 9))
ejArbol2 = N 3(N 2(H 5)(H 7))(N 8(N 6(H 1)(H 4))(H 9))
ejArbol3 = N 3(N 2(H 5)(H 7))(N 8(H 6)(N 9(H 1)(H 4)))
exterior :: Arbol ->[Int]
exterior a =
ramaIzquierda a ++ hojas a ++reverse(tail(ramaDerecha a))-- (ramaIzquierda a) es la rama izquierda del árbol a. Por ejemplo,-- ramaIzquierda ejArbol1 == [3,2,5]-- ramaIzquierda ejArbol3 == [3,2]
ramaIzquierda :: Arbol ->[Int]
ramaIzquierda (H _)=[]
ramaIzquierda (N x i _)= x : ramaIzquierda i
-- (ramaDerecha a) es la rama derecha del árbol a. Por ejemplo,-- ramaDerecha ejArbol1 == [3,8]-- ramaDerecha ejArbol3 == [3,8,9]
ramaDerecha :: Arbol ->[Int]
ramaDerecha (H _)=[]
ramaDerecha (N x _ d)= x : ramaDerecha d
-- (hojas a) es la lista de las hojas del árbol a. Por ejemplo,-- hojas ejArbol1 == [1,4,7,6,9]-- hojas ejArbol3 == [5,7,6,1,4]
hojas :: Arbol ->[Int]
hojas (H x)=[x]
hojas (N _ i d)= hojas i ++ hojas d
data Arbol = H Int
| N Int Arbol Arbol
deriving Show
ejArbol1, ejArbol2, ejArbol3 :: Arbol
ejArbol1 = N 3
(N 2
(N 5 (H 1) (H 4))
(H 7))
(N 8 (H 6) (H 9))
ejArbol2 = N 3
(N 2 (H 5) (H 7))
(N 8 (N 6 (H 1) (H 4))
(H 9))
ejArbol3 = N 3
(N 2 (H 5) (H 7))
(N 8 (H 6)
(N 9 (H 1) (H 4)))
exterior :: Arbol -> [Int]
exterior a =
ramaIzquierda a ++ hojas a ++ reverse (tail (ramaDerecha a))
-- (ramaIzquierda a) es la rama izquierda del árbol a. Por ejemplo,
-- ramaIzquierda ejArbol1 == [3,2,5]
-- ramaIzquierda ejArbol3 == [3,2]
ramaIzquierda :: Arbol -> [Int]
ramaIzquierda (H _) = []
ramaIzquierda (N x i _) = x : ramaIzquierda i
-- (ramaDerecha a) es la rama derecha del árbol a. Por ejemplo,
-- ramaDerecha ejArbol1 == [3,8]
-- ramaDerecha ejArbol3 == [3,8,9]
ramaDerecha :: Arbol -> [Int]
ramaDerecha (H _) = []
ramaDerecha (N x _ d) = x : ramaDerecha d
-- (hojas a) es la lista de las hojas del árbol a. Por ejemplo,
-- hojas ejArbol1 == [1,4,7,6,9]
-- hojas ejArbol3 == [5,7,6,1,4]
hojas :: Arbol -> [Int]
hojas (H x) = [x]
hojas (N _ i d) = hojas i ++ hojas d
Pensamiento
¿Dónde está la utilidad
de nuestras utilidades?
Volvamos a la verdad:
vanidad de vanidades.
(invDigitosPosParesCuadrado (xs,k)) es la lista de los números n tales que xs es la lista de los dígitos de n² en la posiciones pares y k es el número de dígitos de n². Por ejemplo,
Comprobar con QuickCheck que para todo entero positivo n se verifica que para todo entero positivo m, m pertenece a (invDigitosPosParesCuadrado (digitosPosParesCuadrado n)) si, y sólo si, (digitosPosParesCuadrado m) es igual a (digitosPosParesCuadrado n)
Soluciones
import Test.QuickCheck
-- Definición de digitosPosParesCuadrado-- =====================================
digitosPosParesCuadrado ::Integer->([Integer],Int)
digitosPosParesCuadrado n =(digitosPosPares (n^2),length(show(n^2)))-- (digitosPosPares n) es la lista de los dígitos de n en posiciones-- pares. Por ejemplo,-- digitosPosPares 24012019 == [2,0,2,1]
digitosPosPares ::Integer->[Integer]
digitosPosPares n = elementosPosPares (digitos n)-- (digitos n) es la lista de los dígitos de n. Por ejemplo,-- digitos 325 == [3,2,5]
digitos ::Integer->[Integer]
digitos n =[read[c]| c <-show n]-- (elementosPosPares xs) es la lista de los elementos de xs en-- posiciones pares. Por ejemplo,-- elementosPosPares [3,2,5,7,6,4] == [3,5,6]
elementosPosPares ::[a]->[a]
elementosPosPares []=[]
elementosPosPares [x]=[x]
elementosPosPares (x:_:zs)= x : elementosPosPares zs
-- 1ª definición de invDigitosPosParesCuadrado-- ========================================
invDigitosPosParesCuadrado ::([Integer],Int)->[Integer]
invDigitosPosParesCuadrado (xs, a)=[x | x <-[ceiling(sqrt10^(a-1))..ceiling(sqrt10^a)]
, digitosPosParesCuadrado x ==(xs,a)]-- 2ª definición de invDigitosPosParesCuadrado-- ========================================
invDigitosPosParesCuadrado2 ::([Integer],Int)->[Integer]
invDigitosPosParesCuadrado2 x =[n | n <-[a..b], digitosPosParesCuadrado n == x]where a =floor(sqrt(fromIntegral(completaNum x 0)))
b =ceiling(sqrt(fromIntegral(completaNum x 9)))-- (completaNum (xs,k) n) es el número cuyos dígitos en las posiciones-- pares son los de xs y los de las posiciones impares son iguales a n-- (se supone que k es igual al doble de la longitud de xs o un-- menos). Por ejemplo, -- completaNum ([1,3,8],5) 4 == 14348-- completaNum ([1,3,8],6) 4 == 143484
completaNum ::([Integer],Int)->Integer->Integer
completaNum x n = digitosAnumero (completa x n)-- (completa (xs,k) n) es la lista cuyos elementos en las posiciones-- pares son los de xs y los de las posiciones impares son iguales a n-- (se supone que k es igual al doble de la longitud de xs o un-- menos). Por ejemplo, -- completa ([1,3,8],5) 4 == [1,4,3,4,8]-- completa ([1,3,8],6) 4 == [1,4,3,4,8,4]
completa ::([Integer],Int)->Integer->[Integer]
completa (xs,k) n
|even k = ys
|otherwise=init ys
where ys =concat[[x,n]| x <- xs]-- (digitosAnumero ds) es el número cuyos dígitos son ds. Por ejemplo,-- digitosAnumero [2,0,1,9] == 2019
digitosAnumero ::[Integer]->Integer
digitosAnumero =read . concatMapshow-- Comparación de eficiencia-- =========================-- λ> invDigitosPosParesCuadrado ([1,2,1,5,7,4,9],13)-- [1106393,1234567,1314597]-- (7.55 secs, 13,764,850,536 bytes)-- λ> invDigitosPosParesCuadrado2 ([1,2,1,5,7,4,9],13)-- [1106393,1234567,1314597]-- (1.96 secs, 3,780,368,816 bytes)-- Comprobación de la propiedad-- ============================-- La propiedad es
prop_digitosPosParesCuadrado :: Positive Integer-> Positive Integer->Bool
prop_digitosPosParesCuadrado (Positive n)(Positive m)=(digitosPosParesCuadrado m == x)==(m `elem` invDigitosPosParesCuadrado x)where x = digitosPosParesCuadrado n
-- La comprobación es-- λ> quickCheck prop_digitosPosParesCuadrado-- +++ OK, passed 100 tests.
import Test.QuickCheck
-- Definición de digitosPosParesCuadrado
-- =====================================
digitosPosParesCuadrado :: Integer -> ([Integer],Int)
digitosPosParesCuadrado n =
(digitosPosPares (n^2),length (show (n^2)))
-- (digitosPosPares n) es la lista de los dígitos de n en posiciones
-- pares. Por ejemplo,
-- digitosPosPares 24012019 == [2,0,2,1]
digitosPosPares :: Integer -> [Integer]
digitosPosPares n = elementosPosPares (digitos n)
-- (digitos n) es la lista de los dígitos de n. Por ejemplo,
-- digitos 325 == [3,2,5]
digitos :: Integer -> [Integer]
digitos n = [read [c] | c <- show n]
-- (elementosPosPares xs) es la lista de los elementos de xs en
-- posiciones pares. Por ejemplo,
-- elementosPosPares [3,2,5,7,6,4] == [3,5,6]
elementosPosPares :: [a] -> [a]
elementosPosPares [] = []
elementosPosPares [x] = [x]
elementosPosPares (x:_:zs) = x : elementosPosPares zs
-- 1ª definición de invDigitosPosParesCuadrado
-- ========================================
invDigitosPosParesCuadrado :: ([Integer],Int) -> [Integer]
invDigitosPosParesCuadrado (xs, a) =
[x | x <- [ceiling (sqrt 10^(a-1))..ceiling (sqrt 10^a)]
, digitosPosParesCuadrado x == (xs,a)]
-- 2ª definición de invDigitosPosParesCuadrado
-- ========================================
invDigitosPosParesCuadrado2 :: ([Integer],Int) -> [Integer]
invDigitosPosParesCuadrado2 x =
[n | n <- [a..b], digitosPosParesCuadrado n == x]
where a = floor (sqrt (fromIntegral (completaNum x 0)))
b = ceiling (sqrt (fromIntegral (completaNum x 9)))
-- (completaNum (xs,k) n) es el número cuyos dígitos en las posiciones
-- pares son los de xs y los de las posiciones impares son iguales a n
-- (se supone que k es igual al doble de la longitud de xs o un
-- menos). Por ejemplo,
-- completaNum ([1,3,8],5) 4 == 14348
-- completaNum ([1,3,8],6) 4 == 143484
completaNum :: ([Integer],Int) -> Integer -> Integer
completaNum x n = digitosAnumero (completa x n)
-- (completa (xs,k) n) es la lista cuyos elementos en las posiciones
-- pares son los de xs y los de las posiciones impares son iguales a n
-- (se supone que k es igual al doble de la longitud de xs o un
-- menos). Por ejemplo,
-- completa ([1,3,8],5) 4 == [1,4,3,4,8]
-- completa ([1,3,8],6) 4 == [1,4,3,4,8,4]
completa :: ([Integer],Int) -> Integer -> [Integer]
completa (xs,k) n
| even k = ys
| otherwise = init ys
where ys = concat [[x,n] | x <- xs]
-- (digitosAnumero ds) es el número cuyos dígitos son ds. Por ejemplo,
-- digitosAnumero [2,0,1,9] == 2019
digitosAnumero :: [Integer] -> Integer
digitosAnumero = read . concatMap show
-- Comparación de eficiencia
-- =========================
-- λ> invDigitosPosParesCuadrado ([1,2,1,5,7,4,9],13)
-- [1106393,1234567,1314597]
-- (7.55 secs, 13,764,850,536 bytes)
-- λ> invDigitosPosParesCuadrado2 ([1,2,1,5,7,4,9],13)
-- [1106393,1234567,1314597]
-- (1.96 secs, 3,780,368,816 bytes)
-- Comprobación de la propiedad
-- ============================
-- La propiedad es
prop_digitosPosParesCuadrado :: Positive Integer -> Positive Integer -> Bool
prop_digitosPosParesCuadrado (Positive n) (Positive m) =
(digitosPosParesCuadrado m == x)
== (m `elem` invDigitosPosParesCuadrado x)
where x = digitosPosParesCuadrado n
-- La comprobación es
-- λ> quickCheck prop_digitosPosParesCuadrado
-- +++ OK, passed 100 tests.
Pensamiento
¡Ojos que a la luz se abrieron
un día para, después,
ciegos tornar a la tierra,
hartos de mirar sin ver.