Una terna pitagórica con primer lado x es una terna (x,y,z) tal que x^2 + y^2 = z^2. Por ejemplo, las ternas pitagóricas con primer lado 16 son (16,12,20), (16,30,34) y (16,63,65).
(graficaMayorHipotenusa n) dibuja la gráfica de las sucesión de las mayores hipotenusas de las ternas pitagóricas con primer lado x, para x entre 3 y n. Por ejemplo, (graficaMayorHipotenusa 100) dibuja
Soluciones
import Graphics.Gnuplot.Simple
-- Definición de ternasPitagoricas-- ===============================
ternasPitagoricas ::Integer->[(Integer,Integer,Integer)]
ternasPitagoricas x =[(x,y,z)| y <-[1..(x^2-1) `div` 2]
, z <- raizCuadrada (x^2+ y^2)]-- La justificación de la cota es-- x > 2-- x^2 + y^2 >= (y+1)^2-- x^2 + y^2 >= y^2 + 2*y + 1-- y =< (x^ 2 - 1) `div` 2 -- (raizCuadrada x) es la lista formada por la raíz cuadrada entera de-- x, si existe y la lista vacía, en caso contrario. Por ejemplo, -- raizCuadrada 25 == [5]-- raizCuadrada 26 == []
raizCuadrada ::Integer->[Integer]
raizCuadrada x =[y | y <-[(round . sqrt . fromIntegral) x]
, y^2== x]-- 1ª definición de mayorTernaPitagorica-- =====================================
mayorTernaPitagorica ::Integer->(Integer,Integer,Integer)
mayorTernaPitagorica =last . ternasPitagoricas
-- 2ª definición de mayorTernaPitagorica-- =====================================
mayorTernaPitagorica2 ::Integer->(Integer,Integer,Integer)
mayorTernaPitagorica2 x =head[(x,y,z)| y <-[k, k-1 .. 1]
, z <- raizCuadrada (x^2+ y^2)]where k =(x^2-1) `div` 2-- 3ª definición de mayorTernaPitagorica-- =====================================-- Se supone que x > 2. Se consideran dos casos:-- -- Primer caso: Supongamos que x es par. Entonces x^2 > 4 y es divisible-- por 4. Por tanto, existe un y tal que x^2 = 4*y + 4; luego,-- x^2 + y^2 = 4*y + 4 + y^2-- = (y + 2)^2-- La terna es (x,y,y+2) donde y = (x^2 - 4) / 4.---- Segundo caso: Supongamos que x es impar. Entonces x^2 es impar. Por-- tanto, existe un y tal que x^2 = 2*y + 1; luego,-- x^2 + y^2 = 2*y + 1 + y^2-- = (y+1)^2-- La terna es (x,y,y+1) donde y = (x^2 - 1) / 2.
mayorTernaPitagorica3 ::Integer->(Integer,Integer,Integer)
mayorTernaPitagorica3 x
|even x =(x, y1, y1 +2)|otherwise=(x, y2, y2 +1)where y1 =(x^2-4) `div` 4
y2 =(x^2-1) `div` 2-- Comparación de eficiencia-- λ> mayorTernaPitagorica 1006-- (1006,253008,253010)-- (7.36 secs, 1,407,793,992 bytes)-- λ> mayorTernaPitagorica2 1006-- (1006,253008,253010)-- (3.76 secs, 704,007,456 bytes)-- λ> mayorTernaPitagorica3 1006-- (1006,253008,253010)-- (0.01 secs, 157,328 bytes)
graficaMayorHipotenusa ::Integer->IO()
graficaMayorHipotenusa n =
plotList [ Key Nothing
, PNG "Terna_pitagorica_a_partir_de_un_lado.png"][(x,z)| x <-[3..n]
, let(_,_,z)= mayorTernaPitagorica3 x]
import Graphics.Gnuplot.Simple
-- Definición de ternasPitagoricas
-- ===============================
ternasPitagoricas :: Integer -> [(Integer,Integer,Integer)]
ternasPitagoricas x =
[(x,y,z) | y <- [1..(x^ 2 - 1) `div` 2 ]
, z <- raizCuadrada (x^2 + y^2)]
-- La justificación de la cota es
-- x > 2
-- x^2 + y^2 >= (y+1)^2
-- x^2 + y^2 >= y^2 + 2*y + 1
-- y =< (x^ 2 - 1) `div` 2
-- (raizCuadrada x) es la lista formada por la raíz cuadrada entera de
-- x, si existe y la lista vacía, en caso contrario. Por ejemplo,
-- raizCuadrada 25 == [5]
-- raizCuadrada 26 == []
raizCuadrada :: Integer -> [Integer]
raizCuadrada x =
[y | y <- [(round . sqrt . fromIntegral) x]
, y^2 == x]
-- 1ª definición de mayorTernaPitagorica
-- =====================================
mayorTernaPitagorica :: Integer -> (Integer,Integer,Integer)
mayorTernaPitagorica =
last . ternasPitagoricas
-- 2ª definición de mayorTernaPitagorica
-- =====================================
mayorTernaPitagorica2 :: Integer -> (Integer,Integer,Integer)
mayorTernaPitagorica2 x =
head [(x,y,z) | y <- [k, k-1 .. 1]
, z <- raizCuadrada (x^2 + y^2)]
where k = (x^2 - 1) `div` 2
-- 3ª definición de mayorTernaPitagorica
-- =====================================
-- Se supone que x > 2. Se consideran dos casos:
--
-- Primer caso: Supongamos que x es par. Entonces x^2 > 4 y es divisible
-- por 4. Por tanto, existe un y tal que x^2 = 4*y + 4; luego,
-- x^2 + y^2 = 4*y + 4 + y^2
-- = (y + 2)^2
-- La terna es (x,y,y+2) donde y = (x^2 - 4) / 4.
--
-- Segundo caso: Supongamos que x es impar. Entonces x^2 es impar. Por
-- tanto, existe un y tal que x^2 = 2*y + 1; luego,
-- x^2 + y^2 = 2*y + 1 + y^2
-- = (y+1)^2
-- La terna es (x,y,y+1) donde y = (x^2 - 1) / 2.
mayorTernaPitagorica3 :: Integer -> (Integer,Integer,Integer)
mayorTernaPitagorica3 x
| even x = (x, y1, y1 + 2)
| otherwise = (x, y2, y2 + 1)
where y1 = (x^2 - 4) `div` 4
y2 = (x^2 - 1) `div` 2
-- Comparación de eficiencia
-- λ> mayorTernaPitagorica 1006
-- (1006,253008,253010)
-- (7.36 secs, 1,407,793,992 bytes)
-- λ> mayorTernaPitagorica2 1006
-- (1006,253008,253010)
-- (3.76 secs, 704,007,456 bytes)
-- λ> mayorTernaPitagorica3 1006
-- (1006,253008,253010)
-- (0.01 secs, 157,328 bytes)
graficaMayorHipotenusa :: Integer -> IO ()
graficaMayorHipotenusa n =
plotList [ Key Nothing
, PNG "Terna_pitagorica_a_partir_de_un_lado.png"
]
[(x,z) | x <- [3..n]
, let (_,_,z) = mayorTernaPitagorica3 x]
(grafica_raicesEnterasPrimos n) dibuja la gráfica de los n primeros términos de la sucesión de las raíces enteras de los números primos. Por ejemplo, (grafica_raicesEnterasPrimos 200) dibuja
(grafica_posicionesIniciales n) dibuja la gráfica de las menores posiciones de los n primeros números en la sucesión de las raíces enteras de los números primos. Por ejemplo, (grafica_posicionesIniciales 200) dibuja
(grafica_frecuencia n) dibuja la gráfica de las frecuencia de los n primeros números en la sucesión de las raíces enteras de los números primos. Por ejemplo, (grafica_frecuencia 200) dibuja
Soluciones
import Data.Numbers.Primes (primes)import Graphics.Gnuplot.Simple
raicesEnterasPrimos ::[Integer]
raicesEnterasPrimos =map raizEntera primes
raizEntera ::Integer->Integer
raizEntera =floor . sqrt . fromIntegral
posiciones ::Integer->(Int,Int)
posiciones x =(n,n+m-1)where(as,bs)=span(<x) raicesEnterasPrimos
cs =takeWhile(==x) bs
n =lengthas
m =length cs
frecuencia ::Integer->Int
frecuencia x =(length
. takeWhile(==x)
. dropWhile(<x)) raicesEnterasPrimos
grafica_raicesEnterasPrimos ::Int->IO()
grafica_raicesEnterasPrimos n =
plotList [ Title "Raices enteras de primos"
, XLabel "Posiciones de numeros primos"
, YLabel "Raiz entera del n-esimo primo"
, Key Nothing
, PNG "Sucesion_de_raices_enteras_de_primos_1.png"](take n raicesEnterasPrimos)
grafica_posicionesIniciales ::Integer->IO()
grafica_posicionesIniciales n =
plotList [ Title "Posiciones iniciales en raices enteras de primos"
, XLabel "Numeros enteros"
, YLabel "Posicion del numero n en las raices enteras de primos"
, Key Nothing
, PNG "Sucesion_de_raices_enteras_de_primos_2.png"](map(fst . posiciones)[1..n])
grafica_frecuencias ::Integer->IO()
grafica_frecuencias n =
plotList [ Title "Frecuencias en raices enteras de primos"
, XLabel "Numeros enteros n"
, YLabel "Frecuencia del numero n en las raices enteras de primos"
, Key Nothing
, PNG "Sucesion_de_raices_enteras_de_primos_3.png"](map frecuencia [1..n])
import Data.Numbers.Primes (primes)
import Graphics.Gnuplot.Simple
raicesEnterasPrimos :: [Integer]
raicesEnterasPrimos = map raizEntera primes
raizEntera :: Integer -> Integer
raizEntera = floor . sqrt . fromIntegral
posiciones :: Integer -> (Int,Int)
posiciones x = (n,n+m-1)
where (as,bs) = span (<x) raicesEnterasPrimos
cs = takeWhile (==x) bs
n = length as
m = length cs
frecuencia :: Integer -> Int
frecuencia x =
( length
. takeWhile (==x)
. dropWhile (<x)
) raicesEnterasPrimos
grafica_raicesEnterasPrimos :: Int -> IO ()
grafica_raicesEnterasPrimos n =
plotList [ Title "Raices enteras de primos"
, XLabel "Posiciones de numeros primos"
, YLabel "Raiz entera del n-esimo primo"
, Key Nothing
, PNG "Sucesion_de_raices_enteras_de_primos_1.png"
]
(take n raicesEnterasPrimos)
grafica_posicionesIniciales :: Integer -> IO ()
grafica_posicionesIniciales n =
plotList [ Title "Posiciones iniciales en raices enteras de primos"
, XLabel "Numeros enteros"
, YLabel "Posicion del numero n en las raices enteras de primos"
, Key Nothing
, PNG "Sucesion_de_raices_enteras_de_primos_2.png"
]
(map (fst . posiciones) [1..n])
grafica_frecuencias :: Integer -> IO ()
grafica_frecuencias n =
plotList [ Title "Frecuencias en raices enteras de primos"
, XLabel "Numeros enteros n"
, YLabel "Frecuencia del numero n en las raices enteras de primos"
, Key Nothing
, PNG "Sucesion_de_raices_enteras_de_primos_3.png"
]
(map frecuencia [1..n])
Los mayores divisores de un número x son los divisores u tales que u > 1 y existe un v tal que 1 < v < u y u*v = x. Por ejemplo, los mayores divisores de 24 son 12, 8 y 6.
El árbol de los predecesores y mayores divisores de un número x es el árbol cuya raíz es x y los sucesores de cada nodo y > 1 es el conjunto formado por y-1 junto con los mayores divisores de y. Los nodos con valor 1 no tienen sucesores. Por ejemplo, el árbol de los predecesores y mayores divisores del número 6 es
6
/ \
5 3
| |
4 2
/ \ |
3 2 1
| |
2 1
|
1
6
/ \
5 3
| |
4 2
/ \ |
3 2 1
| |
2 1
|
1
Definir las siguientes funciones
mayoresDivisores :: Int -> [Int]
arbol :: Int -> Tree Int
caminos :: Int -> [[Int]]
caminosMinimales :: Int -> [[Int]]
mayoresDivisores :: Int -> [Int]
arbol :: Int -> Tree Int
caminos :: Int -> [[Int]]
caminosMinimales :: Int -> [[Int]]
tales que
(mayoresDivisores x) es la lista de los mayores divisores de x. Por ejemplo,
import Data.Tree
mayoresDivisores ::Int->[Int]
mayoresDivisores x =[max u v | u <-[2..floor(sqrt(fromIntegral x))]
, x `mod` u ==0
, let v = x `div` u]
arbol ::Int-> Tree Int
arbol 1= Node 1[]
arbol x = Node x (arbol (x-1):[arbol y | y <- mayoresDivisores x])
caminos ::Int->[[Int]]
caminos = caminosArbol . arbol
-- λ> caminosArbol (arbol 6)-- [[6,5,4,3,2,1],[6,5,4,2,1],[6,3,2,1]]
caminosArbol :: Tree a ->[[a]]
caminosArbol (Node x [])=[[x]]
caminosArbol (Node x as)=[x:ys | ys <- caminosBosque as]
caminosBosque :: Forest a ->[[a]]
caminosBosque =concatMap caminosArbol
caminosMinimales ::Int->[[Int]]
caminosMinimales x =[ys | ys <- yss, length ys == m]where yss = caminos x
m =minimum(maplength yss)
import Data.Tree
mayoresDivisores :: Int -> [Int]
mayoresDivisores x =
[max u v | u <- [2..floor (sqrt (fromIntegral x))]
, x `mod` u == 0
, let v = x `div` u]
arbol :: Int -> Tree Int
arbol 1 = Node 1 []
arbol x = Node x (arbol (x-1) : [arbol y | y <- mayoresDivisores x])
caminos :: Int -> [[Int]]
caminos = caminosArbol . arbol
-- λ> caminosArbol (arbol 6)
-- [[6,5,4,3,2,1],[6,5,4,2,1],[6,3,2,1]]
caminosArbol :: Tree a -> [[a]]
caminosArbol (Node x []) = [[x]]
caminosArbol (Node x as) = [x:ys | ys <- caminosBosque as]
caminosBosque :: Forest a -> [[a]]
caminosBosque = concatMap caminosArbol
caminosMinimales :: Int -> [[Int]]
caminosMinimales x = [ys | ys <- yss, length ys == m]
where yss = caminos x
m = minimum (map length yss)
tal que (sumasDe2Cuadrados n) es la lista de los pares de números tales que la suma de sus cuadrados es n y el primer elemento del par es mayor o igual que el segundo. Por ejemplo,
Un número oblongo es un número que es el producto de dos números naturales consecutivos; es decir, n es un número oblongo si existe un número natural x tal que n = x(x+1). Por ejemplo, 42 es un número oblongo porque 42 = 6 x 7.
-- 1ª definición de esOblongo
esOblongo1 ::Integer->Bool
esOblongo1 n =
n == x *(x+1)where x =round(sqrt(fromIntegral n))-- 2ª definición de esOblongo
esOblongo2 ::Integer->Bool
esOblongo2 n =
n `pertenece` oblongos3
pertenece ::Integer->[Integer]->Bool
pertenece x ys =
x ==head(dropWhile(< x) ys)-- 1ª definición de oblongos
oblongos1 ::[Integer]
oblongos1 =[n | n <-[0..]
, esOblongo1 n]-- 2ª definición de oblongos
oblongos2 ::[Integer]
oblongos2 =filter esOblongo1 [0..]-- 3ª definición de oblongos
oblongos3 ::[Integer]
oblongos3 =zipWith(*)[0..][1..]
-- 1ª definición de esOblongo
esOblongo1 :: Integer -> Bool
esOblongo1 n =
n == x * (x+1)
where x = round (sqrt (fromIntegral n))
-- 2ª definición de esOblongo
esOblongo2 :: Integer -> Bool
esOblongo2 n =
n `pertenece` oblongos3
pertenece :: Integer -> [Integer] -> Bool
pertenece x ys =
x == head (dropWhile (< x) ys)
-- 1ª definición de oblongos
oblongos1 :: [Integer]
oblongos1 = [n | n <- [0..]
, esOblongo1 n]
-- 2ª definición de oblongos
oblongos2 :: [Integer]
oblongos2 = filter esOblongo1 [0..]
-- 3ª definición de oblongos
oblongos3 :: [Integer]
oblongos3 = zipWith (*) [0..] [1..]
Las descomposiciones de un número n son las parejas de números (x,y) tales que x >= y y la suma de las cuatro operaciones básicas (suma, producto, resta (el mayor menos el menor) y cociente (el mayor entre el menor)) es el número n. Por ejemplo, (8,2) es una descomposición de 36 ya que
(8 + 2) + (8 - 2) + (8 * 2) + (8 / 2) = 36
(8 + 2) + (8 - 2) + (8 * 2) + (8 / 2) = 36
Un número es completo si tiene alguna descomposición como las anteriores. Por ejemplo, el 36 es completo pero el 21 no lo es.
Un número entero positivo es libre de cuadrados si no es divisible el cuadrado de ningún entero mayor que 1. Por ejemplo, 70 es libre de cuadrado porque sólo es divisible por 1, 2, 5, 7 y 70; en cambio, 40 no es libre de cuadrados porque es divisible por 2^2.
Definir la función
libreDeCuadrados :: Integer -> Bool
libreDeCuadrados :: Integer -> Bool
tal que (libreDeCuadrados x) se verifica si x es libre de cuadrados. Por ejemplo,
Los números de Catalan satisfacen la siguiente relación de recurrencia:
Asintóticamente, los números de Catalan crecen como:
considerando que el cociente entre el n-ésimo número de Catalan y la expresión de la derecha tiende hacia 1 cuando n tiende a infinito.
Definir las funciones
catalan :: [Integer]
grafica :: Int -> Int -> IO ()
catalan :: [Integer]
grafica :: Int -> Int -> IO ()
tales que
catalan es la lista de términos de la sucesión de Catalan. Por ejemplo,
(grafica a b) dibuja los n-ésimos términos de la sucesión de Catalan, para n entre a y b, junto con los de la expresión de la derecha de
Por ejemplo, (grafica 5 10) dibuja
y (grafica 55 60) dibuja
Soluciones
import Graphics.Gnuplot.Simple
catalan ::[Integer]
catalan =scanl(\c n -> c*2*(2*n-1) `div` (n+1))1[1..]
grafica ::Int->Int->IO()
grafica a b =
plotLists [Key Nothing][[(fromIntegral n, fromIntegral(catalan !! n))| n <-[a..b]]
,[(n,4**n/(n**(3/2)*(sqrtpi)))| n <-[c..d]]]where c, d ::Double
c =fromIntegral a
d =fromIntegral b
import Graphics.Gnuplot.Simple
catalan :: [Integer]
catalan = scanl (\c n -> c*2*(2*n-1) `div` (n+1)) 1 [1..]
grafica :: Int -> Int -> IO ()
grafica a b =
plotLists [Key Nothing]
[[(fromIntegral n, fromIntegral (catalan !! n)) | n <- [a..b]]
,[(n,4**n/(n**(3/2)*(sqrt pi))) | n <- [c..d]]]
where c, d :: Double
c = fromIntegral a
d = fromIntegral b
Los mayores divisores de un número x son los divisores u tales que u > 1 y existe un v tal que 1 < v < u y u*v = x. Por ejemplo, los mayores divisores de 24 son 12, 8 y 6.
El árbol de los predecesores y mayores divisores de un número x es el árbol cuya raíz es x y los sucesores de cada nodo y > 1 es el conjunto formado por y-1 junto con los mayores divisores de y. Los nodos con valor 1 no tienen sucesores. Por ejemplo, el árbol de los predecesores y mayores divisores del número 6 es
6
/ \
5 3
| |
4 2
/ \ |
3 2 1
| |
2 1
|
1
6
/ \
5 3
| |
4 2
/ \ |
3 2 1
| |
2 1
|
1
Definir las siguientes funciones
mayoresDivisores :: Int -> [Int]
arbol :: Int -> Tree Int
caminos :: Int -> [[Int]]
caminosMinimales :: Int -> [[Int]]
mayoresDivisores :: Int -> [Int]
arbol :: Int -> Tree Int
caminos :: Int -> [[Int]]
caminosMinimales :: Int -> [[Int]]
tales que
(mayoresDivisores x) es la lista de los mayores divisores de x. Por ejemplo,
import Data.Tree
mayoresDivisores ::Int->[Int]
mayoresDivisores x =[max u v | u <-[2..floor(sqrt(fromIntegral x))]
, x `mod` u ==0
, let v = x `div` u]
arbol ::Int-> Tree Int
arbol 1= Node 1[]
arbol x = Node x (arbol (x-1):[arbol y | y <- mayoresDivisores x])
caminos ::Int->[[Int]]
caminos = caminosArbol . arbol
-- λ> caminosArbol (arbol 6)-- [[6,5,4,3,2,1],[6,5,4,2,1],[6,3,2,1]]
caminosArbol :: Tree a ->[[a]]
caminosArbol (Node x [])=[[x]]
caminosArbol (Node x as)=[x:ys | ys <- caminosBosque as]
caminosBosque :: Forest a ->[[a]]
caminosBosque =concatMap caminosArbol
caminosMinimales ::Int->[[Int]]
caminosMinimales x =[ys | ys <- yss, length ys == m]where yss = caminos x
m =minimum(maplength yss)
import Data.Tree
mayoresDivisores :: Int -> [Int]
mayoresDivisores x =
[max u v | u <- [2..floor (sqrt (fromIntegral x))]
, x `mod` u == 0
, let v = x `div` u]
arbol :: Int -> Tree Int
arbol 1 = Node 1 []
arbol x = Node x (arbol (x-1) : [arbol y | y <- mayoresDivisores x])
caminos :: Int -> [[Int]]
caminos = caminosArbol . arbol
-- λ> caminosArbol (arbol 6)
-- [[6,5,4,3,2,1],[6,5,4,2,1],[6,3,2,1]]
caminosArbol :: Tree a -> [[a]]
caminosArbol (Node x []) = [[x]]
caminosArbol (Node x as) = [x:ys | ys <- caminosBosque as]
caminosBosque :: Forest a -> [[a]]
caminosBosque = concatMap caminosArbol
caminosMinimales :: Int -> [[Int]]
caminosMinimales x = [ys | ys <- yss, length ys == m]
where yss = caminos x
m = minimum (map length yss)