tal que (mezcla xss) es la lista tomando sucesivamente los elementos de xss en la misma posición. Cuando una de las listas de xss es vacía, se continua con las restantes. por ejemplo,
(tabla f ns) escribe en el fichero f las n-ésimas aproximaciones de pi, donde n toma los valores de la lista ns, junto con sus errores. Por ejemplo, al evaluar la expresión
tabla "AproximacionesPi.txt" [0,10..100]
tabla "AproximacionesPi.txt" [0,10..100]
hace que el contenido del fichero “AproximacionesPi.txt” sea
import Text.Printf
-- 1ª solución-- ===========
aproximacionPi ::Int->Double
aproximacionPi n = serieNilakantha !! n
serieNilakantha ::[Double]
serieNilakantha =scanl1(+) terminosNilakantha
terminosNilakantha ::[Double]
terminosNilakantha =zipWith(/) numeradores denominadores
where numeradores =3:cycle[4,-4]
denominadores =1:[n*(n+1)*(n+2)| n <-[2,4..]]-- 2ª solución-- ===========
aproximacionPi2 ::Int->Double
aproximacionPi2 = aux 321where aux x _ _ 0= x
aux x y z m =
aux (x+4/product[y..y+2]*z)(y+2)(negate z)(m-1)-- 3ª solución-- ===========
aproximacionPi3 ::Int->Double
aproximacionPi3 x =3+sum[(((-1)**(n+1))*4)/(2*n*(2*n+1)*(2*n+2))| n <-[1..fromIntegral x]]-- Comparación de eficiencia-- =========================-- λ> aproximacionPi (10^6)-- 3.141592653589787-- (1.35 secs, 729,373,160 bytes)-- λ> aproximacionPi2 (10^6)-- 3.141592653589787-- (2.96 secs, 2,161,766,096 bytes)-- λ> aproximacionPi3 (10^6)-- 3.1415926535897913-- (2.02 secs, 1,121,372,536 bytes)-- Definicioń de tabla-- ===================
tabla :: FilePath ->[Int]->IO()
tabla f ns =writeFile f (tablaAux ns)
tablaAux ::[Int]->String
tablaAux ns =
linea
++ cabecera
++ linea
++concat[printf "| %4d | %.12f | %.12f |\n" n a e
| n <- ns
, let a = aproximacionPi n
, let e =abs(pi- a)]++ linea
linea ::String
linea ="+------+----------------+----------------+\n"
cabecera ::String
cabecera ="| n | Aproximación | Error |\n"
import Text.Printf
-- 1ª solución
-- ===========
aproximacionPi :: Int -> Double
aproximacionPi n = serieNilakantha !! n
serieNilakantha :: [Double]
serieNilakantha = scanl1 (+) terminosNilakantha
terminosNilakantha :: [Double]
terminosNilakantha = zipWith (/) numeradores denominadores
where numeradores = 3 : cycle [4,-4]
denominadores = 1 : [n*(n+1)*(n+2) | n <- [2,4..]]
-- 2ª solución
-- ===========
aproximacionPi2 :: Int -> Double
aproximacionPi2 = aux 3 2 1
where aux x _ _ 0 = x
aux x y z m =
aux (x+4/product[y..y+2]*z) (y+2) (negate z) (m-1)
-- 3ª solución
-- ===========
aproximacionPi3 :: Int -> Double
aproximacionPi3 x =
3 + sum [(((-1)**(n+1))*4)/(2*n*(2*n+1)*(2*n+2))
| n <- [1..fromIntegral x]]
-- Comparación de eficiencia
-- =========================
-- λ> aproximacionPi (10^6)
-- 3.141592653589787
-- (1.35 secs, 729,373,160 bytes)
-- λ> aproximacionPi2 (10^6)
-- 3.141592653589787
-- (2.96 secs, 2,161,766,096 bytes)
-- λ> aproximacionPi3 (10^6)
-- 3.1415926535897913
-- (2.02 secs, 1,121,372,536 bytes)
-- Definicioń de tabla
-- ===================
tabla :: FilePath -> [Int] -> IO ()
tabla f ns = writeFile f (tablaAux ns)
tablaAux :: [Int] -> String
tablaAux ns =
linea
++ cabecera
++ linea
++ concat [printf "| %4d | %.12f | %.12f |\n" n a e
| n <- ns
, let a = aproximacionPi n
, let e = abs (pi - a)]
++ linea
linea :: String
linea = "+------+----------------+----------------+\n"
cabecera :: String
cabecera = "| n | Aproximación | Error |\n"
Pensamiento
Bueno es saber que los vasos
nos sirven para beber;
lo malo es que no sabemos
para que sirve la sed.
imparesPascal es la lista de los elementos impares en cada una de las filas del triángulo de Pascal. Por ejemplo,
λ> take 8 imparesPascal
[[1],[1,1],[1,1],[1,3,3,1],[1,1],[1,5,5,1],[1,15,15,1],[1,7,21,35,35,21,7,1]]
λ> take 8 imparesPascal
[[1],[1,1],[1,1],[1,3,3,1],[1,1],[1,5,5,1],[1,15,15,1],[1,7,21,35,35,21,7,1]]
nImparesPascal es la lista del número de elementos impares en cada una de las filas del triángulo de Pascal. Por ejemplo,
λ> take 32 nImparesPascal
[1,2,2,4,2,4,4,8,2,4,4,8,4,8,8,16,2,4,4,8,4,8,8,16,4,8,8,16,8,16,16,32]
λ> maximum (take (10^6) nImparesPascal3)
524288
λ> take 32 nImparesPascal
[1,2,2,4,2,4,4,8,2,4,4,8,4,8,8,16,2,4,4,8,4,8,8,16,4,8,8,16,8,16,16,32]
λ> maximum (take (10^6) nImparesPascal3)
524288
(grafica_nImparesPascal n) dibuja la gráfica de los n primeros términos de nImparesPascal. Por ejemplo, (grafica_nImparesPascal 50) dibuja
y (grafica_nImparesPascal 100) dibuja
Comprobar con QuickCheck que todos los elementos de nImparesPascal son potencias de dos.
Soluciones
import Data.List (transpose)import Test.QuickCheck
import Graphics.Gnuplot.Simple
-- 1ª definición de imparesPascal-- ==============================
imparesPascal ::[[Integer]]
imparesPascal =map(filterodd) pascal
-- pascal es la lista de las filas del triángulo de Pascal. Por ejemplo,-- λ> take 7 pascal-- [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1],[1,6,15,20,15,6,1]]
pascal ::[[Integer]]
pascal =[1]:map f pascal
where f xs =zipWith(+)(0:xs)(xs++[0])-- 2ª definición de imparesPascal-- ==============================
imparesPascal2 ::[[Integer]]
imparesPascal2 =map(filterodd) pascal
pascal2 ::[[Integer]]
pascal2 =iterate f [1]where f xs =zipWith(+)(0:xs)(xs++[0])-- 1ª definición de nImparesPascal-- ===============================
nImparesPascal ::[Int]
nImparesPascal =maplength imparesPascal
-- 2ª definición de nImparesPascal-- ===============================
nImparesPascal2 ::[Int]
nImparesPascal2 =map(length . filterodd) imparesPascal
-- 3ª definición de nImparesPascal-- ===============================-- λ> take 32 nImparesPascal2-- [1,2,-- 2,4,-- 2,4,4,8,-- 2,4,4,8,4,8,8,16,-- 2,4,4,8,4,8,8,16,4,8,8,16,8,16,16,32]
nImparesPascal3 ::[Int]
nImparesPascal3 =1: zs
where zs =2:concat(transpose [zs, map(*2) zs])-- Definición de grafica_nImparesPascal-- =========================================
grafica_nImparesPascal ::Int->IO()
grafica_nImparesPascal n =
plotListStyle
[ Key Nothing
, PNG ("Impares_en_filas_del_triangulo_de_Pascal_"++show n ++".png")](defaultStyle {plotType = LinesPoints})(take n nImparesPascal3)-- Propiedad de nImparesPascal-- ===========================-- La propiedad es
prop_nImparesPascal :: Positive Int->Bool
prop_nImparesPascal (Positive n)=
esPotenciaDeDos (nImparesPascal3 !! n)-- (esPotenciaDeDos n) se verifica si n es una potencia de dos. Por-- ejemplo,-- esPotenciaDeDos 16 == True-- esPotenciaDeDos 18 == False
esPotenciaDeDos ::Int->Bool
esPotenciaDeDos 1= True
esPotenciaDeDos n =even n && esPotenciaDeDos (n `div` 2)-- La comprobación es-- λ> quickCheck prop_nImparesPascal-- +++ OK, passed 100 tests.
import Data.List (transpose)
import Test.QuickCheck
import Graphics.Gnuplot.Simple
-- 1ª definición de imparesPascal
-- ==============================
imparesPascal :: [[Integer]]
imparesPascal =
map (filter odd) pascal
-- pascal es la lista de las filas del triángulo de Pascal. Por ejemplo,
-- λ> take 7 pascal
-- [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1],[1,6,15,20,15,6,1]]
pascal :: [[Integer]]
pascal = [1] : map f pascal
where f xs = zipWith (+) (0:xs) (xs++[0])
-- 2ª definición de imparesPascal
-- ==============================
imparesPascal2 :: [[Integer]]
imparesPascal2 =
map (filter odd) pascal
pascal2 :: [[Integer]]
pascal2 = iterate f [1]
where f xs = zipWith (+) (0:xs) (xs++[0])
-- 1ª definición de nImparesPascal
-- ===============================
nImparesPascal :: [Int]
nImparesPascal =
map length imparesPascal
-- 2ª definición de nImparesPascal
-- ===============================
nImparesPascal2 :: [Int]
nImparesPascal2 =
map (length . filter odd) imparesPascal
-- 3ª definición de nImparesPascal
-- ===============================
-- λ> take 32 nImparesPascal2
-- [1,2,
-- 2,4,
-- 2,4,4,8,
-- 2,4,4,8,4,8,8,16,
-- 2,4,4,8,4,8,8,16,4,8,8,16,8,16,16,32]
nImparesPascal3 :: [Int]
nImparesPascal3 = 1 : zs
where zs = 2 : concat (transpose [zs, map (*2) zs])
-- Definición de grafica_nImparesPascal
-- =========================================
grafica_nImparesPascal :: Int -> IO ()
grafica_nImparesPascal n =
plotListStyle
[ Key Nothing
, PNG ("Impares_en_filas_del_triangulo_de_Pascal_" ++ show n ++ ".png")
]
(defaultStyle {plotType = LinesPoints})
(take n nImparesPascal3)
-- Propiedad de nImparesPascal
-- ===========================
-- La propiedad es
prop_nImparesPascal :: Positive Int -> Bool
prop_nImparesPascal (Positive n) =
esPotenciaDeDos (nImparesPascal3 !! n)
-- (esPotenciaDeDos n) se verifica si n es una potencia de dos. Por
-- ejemplo,
-- esPotenciaDeDos 16 == True
-- esPotenciaDeDos 18 == False
esPotenciaDeDos :: Int -> Bool
esPotenciaDeDos 1 = True
esPotenciaDeDos n = even n && esPotenciaDeDos (n `div` 2)
-- La comprobación es
-- λ> quickCheck prop_nImparesPascal
-- +++ OK, passed 100 tests.
Pensamiento
De lo que llaman los hombres
virtud, justicia y bondad,
una mitad es envidia,
y la otra no es caridad.
ej1, ej2, ej3 :: Arbol Int
ej1 = N 1 [N 2 [N 4 [], N 5 []], N 3 [N 6 [], N 7 []]]
ej2 = N 1 [N 8 [], N 3 [N 4 [], N 5 [], N 6 []]]
ej3 = N 1 [N 8 [N 4 [], N 5 [], N 6 []], N 3 [N 7 []]]
ej1, ej2, ej3 :: Arbol Int
ej1 = N 1 [N 2 [N 4 [], N 5 []], N 3 [N 6 [], N 7 []]]
ej2 = N 1 [N 8 [], N 3 [N 4 [], N 5 [], N 6 []]]
ej3 = N 1 [N 8 [N 4 [], N 5 [], N 6 []], N 3 [N 7 []]]
Definir la función
espiral :: Arbol a -> [a]
espiral :: Arbol a -> [a]
tal que (espiral x) es la lista de los nodos del árbol x recorridos en espiral; es decir, la raíz de x, los nodos del primer nivel de izquierda a derecha, los nodos del segundo nivel de derecha a izquierda y así sucesivamente. Por ejemplo,
data Arbol a = N a [Arbol a]derivingShow
ej1, ej2, ej3 :: Arbol Int
ej1 = N 1[N 2[N 4[], N 5[]], N 3[N 6[], N 7[]]]
ej2 = N 1[N 8[], N 3[N 4[], N 5[], N 6[]]]
ej3 = N 1[N 8[N 4[], N 5[], N 6[]], N 3[N 7[]]]-- 1ª solución-- ===========
espiral :: Arbol a ->[a]
espiral x =concat[f xs |(f,xs)<-zip(cycle[reverse,id])(niveles x)]-- (niveles x) es la lista de los niveles del árbol x. Por ejemplo, -- niveles ej1 == [[1],[8,3],[4]]-- niveles ej2 == [[1],[8,3],[4,5,6]]-- niveles ej3 == [[1],[8,3],[4,5,6,7]]
niveles :: Arbol a ->[[a]]
niveles x =takeWhile(not . null)[nivel n x | n <-[0..]]-- (nivel n x) es el nivel de nivel n del árbol x. Por ejemplo,-- nivel 0 ej1 == [1]-- nivel 1 ej1 == [8,3]-- nivel 2 ej1 == [4]-- nivel 4 ej1 == []
nivel ::Int-> Arbol a ->[a]
nivel 0(N x _)=[x]
nivel n (N _ xs)=concatMap(nivel (n-1)) xs
-- 2ª solución-- ===========
espiral2 :: Arbol a ->[a]
espiral2 =concat . zipWith($)(cycle[reverse,id]) . niveles
-- 3ª solución-- ===========
espiral3 :: Arbol a ->[a]
espiral3 =concat . zipWith($)(cycle[reverse,id]) . niveles3
niveles3 :: Arbol a ->[[a]]
niveles3 t =map(map raiz)
. takeWhile(not . null)
. iterate(concatMap subBosque)$[t]
raiz :: Arbol a -> a
raiz (N x _)= x
subBosque :: Arbol a ->[Arbol a]
subBosque (N _ ts)= ts
-- 4ª solución-- ===========
espiral4 :: Arbol a ->[a]
espiral4 =concat . zipWith($)(cycle[reverse,id]) . niveles4
niveles4 :: Arbol a ->[[a]]
niveles4 =map(map raiz)
. takeWhile(not . null)
. iterate(concatMap subBosque)
. return-- 5ª definición-- =============
espiral5 :: Arbol a ->[a]
espiral5 x =concat$zipWith($)(cycle[reverse,id])$ niveles5 [x]
niveles5 ::[Arbol a]->[[a]]
niveles5 []=[]
niveles5 xs = a : niveles5 (concat b)where(a,b)=unzip$map(\(N x y)->(x,y)) xs
-- 6ª definición-- =============
espiral6 :: Arbol a ->[a]
espiral6 =concat . zipWith($)(cycle[reverse,id]) . niveles5 . return
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 [N 6 [], N 7 []]]
ej2 = N 1 [N 8 [], N 3 [N 4 [], N 5 [], N 6 []]]
ej3 = N 1 [N 8 [N 4 [], N 5 [], N 6 []], N 3 [N 7 []]]
-- 1ª solución
-- ===========
espiral :: Arbol a -> [a]
espiral x =
concat [f xs | (f,xs) <- zip (cycle [reverse,id]) (niveles x)]
-- (niveles x) es la lista de los niveles del árbol x. Por ejemplo,
-- niveles ej1 == [[1],[8,3],[4]]
-- niveles ej2 == [[1],[8,3],[4,5,6]]
-- niveles ej3 == [[1],[8,3],[4,5,6,7]]
niveles :: Arbol a -> [[a]]
niveles x = takeWhile (not . null) [nivel n x | n <- [0..]]
-- (nivel n x) es el nivel de nivel n del árbol x. Por ejemplo,
-- nivel 0 ej1 == [1]
-- nivel 1 ej1 == [8,3]
-- nivel 2 ej1 == [4]
-- nivel 4 ej1 == []
nivel :: Int -> Arbol a -> [a]
nivel 0 (N x _) = [x]
nivel n (N _ xs) = concatMap (nivel (n-1)) xs
-- 2ª solución
-- ===========
espiral2 :: Arbol a -> [a]
espiral2 =
concat . zipWith ($) (cycle [reverse,id]) . niveles
-- 3ª solución
-- ===========
espiral3 :: Arbol a -> [a]
espiral3 = concat . zipWith ($) (cycle [reverse,id]) . niveles3
niveles3 :: Arbol a -> [[a]]
niveles3 t = map (map raiz)
. takeWhile (not . null)
. iterate (concatMap subBosque) $ [t]
raiz :: Arbol a -> a
raiz (N x _) = x
subBosque :: Arbol a -> [Arbol a]
subBosque (N _ ts) = ts
-- 4ª solución
-- ===========
espiral4 :: Arbol a -> [a]
espiral4 = concat . zipWith ($) (cycle [reverse,id]) . niveles4
niveles4 :: Arbol a -> [[a]]
niveles4 = map (map raiz)
. takeWhile (not . null)
. iterate (concatMap subBosque)
. return
-- 5ª definición
-- =============
espiral5 :: Arbol a -> [a]
espiral5 x = concat $ zipWith ($) (cycle [reverse,id]) $ niveles5 [x]
niveles5 :: [Arbol a] -> [[a]]
niveles5 [] = []
niveles5 xs = a : niveles5 (concat b)
where (a,b) = unzip $ map (\(N x y) -> (x,y)) xs
-- 6ª definición
-- =============
espiral6 :: Arbol a -> [a]
espiral6 = concat . zipWith ($) (cycle [reverse,id]) . niveles5 . return
Pensamiento
Dice la monotonía
del agua clara al caer:
un día es como otro día;
hoy es lo mismo que ayer.
(graficaSucTriangular n) dibuja la gráfica de los n primeros términos de la sucesión triangular. Por ejemplo, (graficaSucTriangular 300) dibuja
Soluciones
import Data.List (inits)import Test.QuickCheck
import Graphics.Gnuplot.Simple
-- 1ª definición de sucTriangular -- ==============================
sucTriangular ::[Integer]
sucTriangular =concat[[1..n]| n <-[1..]]-- 2ª definición de sucTriangular -- ==============================
sucTriangular2 ::[Integer]
sucTriangular2 =[x | n <-[1..], x <-[1..n]]-- 3ª definición de sucTriangular -- ==============================
sucTriangular3 ::[Integer]
sucTriangular3 =concat(tail(inits [1..]))-- 1ª definición de terminoSucTriangular-- =====================================
terminoSucTriangular ::Int->Integer
terminoSucTriangular k =
sucTriangular !! k
-- 2ª definición de terminoSucTriangular-- =====================================
terminoSucTriangular2 ::Int->Integer
terminoSucTriangular2 k =
sucTriangular2 !! k
-- 3ª definición de terminoSucTriangular-- =====================================
terminoSucTriangular3 ::Int->Integer
terminoSucTriangular3 k =
sucTriangular3 !! k
-- Equivalencia de definiciones-- ============================-- La propiedad es
prop_terminoTriangular :: Positive Int->Bool
prop_terminoTriangular (Positive n)=
terminoSucTriangular n == terminoSucTriangular2 n &&
terminoSucTriangular n == terminoSucTriangular3 n
-- La comprobación es-- λ> quickCheck prop_terminoTriangular-- +++ OK, passed 100 tests.-- Comparación de eficiencia-- =========================-- λ> terminoSucTriangular (3*10^6)-- 2425-- (2.07 secs, 384,707,936 bytes)-- λ> terminoSucTriangular2 (3*10^6)-- 2425-- (2.22 secs, 432,571,208 bytes)-- λ> terminoSucTriangular3 (3*10^6)-- 2425-- (0.69 secs, 311,259,504 bytes)-- Definición de graficaSucTriangular-- ==================================
graficaSucTriangular ::Int->IO()
graficaSucTriangular n =
plotList [ Key Nothing
, PNG "Sucesion_triangular.png"](take n sucTriangular)
import Data.List (inits)
import Test.QuickCheck
import Graphics.Gnuplot.Simple
-- 1ª definición de sucTriangular
-- ==============================
sucTriangular :: [Integer]
sucTriangular =
concat [[1..n] | n <- [1..]]
-- 2ª definición de sucTriangular
-- ==============================
sucTriangular2 :: [Integer]
sucTriangular2 =
[x | n <- [1..], x <- [1..n]]
-- 3ª definición de sucTriangular
-- ==============================
sucTriangular3 :: [Integer]
sucTriangular3 =
concat (tail (inits [1..]))
-- 1ª definición de terminoSucTriangular
-- =====================================
terminoSucTriangular :: Int -> Integer
terminoSucTriangular k =
sucTriangular !! k
-- 2ª definición de terminoSucTriangular
-- =====================================
terminoSucTriangular2 :: Int -> Integer
terminoSucTriangular2 k =
sucTriangular2 !! k
-- 3ª definición de terminoSucTriangular
-- =====================================
terminoSucTriangular3 :: Int -> Integer
terminoSucTriangular3 k =
sucTriangular3 !! k
-- Equivalencia de definiciones
-- ============================
-- La propiedad es
prop_terminoTriangular :: Positive Int -> Bool
prop_terminoTriangular (Positive n) =
terminoSucTriangular n == terminoSucTriangular2 n &&
terminoSucTriangular n == terminoSucTriangular3 n
-- La comprobación es
-- λ> quickCheck prop_terminoTriangular
-- +++ OK, passed 100 tests.
-- Comparación de eficiencia
-- =========================
-- λ> terminoSucTriangular (3*10^6)
-- 2425
-- (2.07 secs, 384,707,936 bytes)
-- λ> terminoSucTriangular2 (3*10^6)
-- 2425
-- (2.22 secs, 432,571,208 bytes)
-- λ> terminoSucTriangular3 (3*10^6)
-- 2425
-- (0.69 secs, 311,259,504 bytes)
-- Definición de graficaSucTriangular
-- ==================================
graficaSucTriangular :: Int -> IO ()
graficaSucTriangular n =
plotList [ Key Nothing
, PNG "Sucesion_triangular.png"
]
(take n sucTriangular)
Pensamiento
Nadie debe asustarse de lo que piensa, aunque su pensar aparezca en pugna con las leyes más elementales de la lógica. Porque todo ha de ser pensado por alguien, y el mayor desatino puede ser un punto de vista de lo real.