Ir al contenido principal

Anotación de la profundidad de los nodos

Los árboles binarios con datos en los nodos y hojas se definen por

data Arbol a = H
             | N a (Arbol a) (Arbol a)
             deriving (Eq, Show)

Por ejemplo, el árbol

       3
      / \
     /   \
    4     7
   / \   / \
  5   0 0   3
 / \
2   0

se representa por

ejArbol :: Arbol Integer
ejArbol = N 3 (N 4 (N 5 (H 2)(H 0)) (H 0)) (N 7 (H 0) (H 3))

Anotando cada elemento del árbol anterior con su profundidad, se obtiene el árbol siguiente

        3-0
        / \
       /   \
      /     \
    4-1     7-1
    / \     / \
  5-2 0-2 0-2 3-0
  / \
2-3 0-3

Definir la función

anotado :: Arbol a -> Arbol (a,Int)

tal que (anotado x) es el árbol obtenido anotando los elementos de x con su profundidad. Por ejemplo,

λ> anotado ejArbol
N (3,0)
  (N (4,1)
     (N (5,2) (H (2,3)) (H (0,3)))
     (H (0,2)))
  (N (7,1) (H (0,2)) (H (3,2)))

Leer más…

Compactación de listas

Definir la función

compactada :: [Maybe Int] -> [Int]

tal que (compacta xs) es la lista obtenida al compactar xs con las siguientes reglas:

  1. se eliminan los elementos Nothing;
  2. si dos elementos consecutivos tienen el mismo valor, se sustituyen por el sucesor de su valor y
  3. los restantes elementos no se cambian.

Por ejemplo,

λ> compactada [Just 1,Nothing,Just 1,Just 4,Just 4,Just 3,Just 6]
[2,5,3,6]
λ> compactada [Just 1,Nothing,Just 1,Just 1,Just 4,Just 3,Just 6]
[2,1,4,3,6]
λ> compactada [Just 1,Nothing,Just 1,Just 1,Just 4,Just 4,Just 6]
[2,1,5,6]
λ> compactada [Just 1,Nothing,Just 1,Just 1,Just 4,Just 3,Just 4]
[2,1,4,3,4]
λ> compactada [Just 1,Nothing,Just 1,Just 2,Just 4,Just 3,Just 4]
[2,2,4,3,4]

Leer más…

Número de representaciones de n como suma de dos cuadrados

Sea \( n \) un número natural cuya factorización prima es \[ n = 2^a \cdot p_1^{b_1} \cdots p_n^{b_n} \cdot q_1^{c_1} \cdots q_m^{c_m} \] donde los \( p_i \) son los divisores primos de \( n \) congruentes con \( 3 \) módulo \( 4 \) y los \( q_j \) son los divisores primos de \( n \) congruentes con \( 1 \) módulo \( 4 \). Entonces, el número de formas de descomponer \( n \) como suma de dos cuadrados es \( 0 \), si algún \( b_i \) es impar y es el techo (es decir, el número entero más próximo por exceso) de \[ \frac{(1+c_1) \cdots (1+c_m)}{2} \] en caso contrario. Por ejemplo, el número \( 2^3 \cdot (3^9 \cdot 7^8) \cdot (5^3 \cdot 13^6) \) no se puede descomponer como sumas de dos cuadrados (porque el exponente de \( 3 \) es impar) y el número \( 2^3 \cdot (3^2 \cdot 7^8) \cdot (5^3 \cdot 13^6) \) tiene \( 14 \) descomposiciones como suma de dos cuadrados (porque los exponentes de \( 3 \) y \( 7 \) son pares y el techo de \( \frac{(1+3)(1+6)}{2} \) es \( 14 \)).

Definir la función

   nRepresentaciones :: Integer -> Integer

tal que (nRepresentaciones n) es el número de formas de representar n como suma de dos cuadrados. Por ejemplo,

   nRepresentaciones (2^3*3^9*5^3*7^8*13^6)        ==  0
   nRepresentaciones (2^3*3^2*5^3*7^8*13^6)        ==  14
   head [n | n <- [1..], nRepresentaciones n > 8]  ==  71825

Usando la función representaciones del ejercicio anterior, comprobar con QuickCheck la siguiente propiedad

prop_nRepresentaciones :: Integer -> Property
prop_nRepresentaciones n =
    n > 0 ==>
      nRepresentaciones2 n == genericLength (representaciones n)

Leer más…

Representaciones de un número como suma de dos cuadrados

Definir la función

representaciones :: Integer -> [(Integer,Integer)]

tal que (representaciones n) es la lista de pares de números naturales (x,y) tales que n = x^2 + y^2. Por ejemplo.

representaciones  20           ==  [(2,4)]
representaciones  25           ==  [(0,5),(3,4)]
representaciones 325           ==  [(1,18),(6,17),(10,15)]
representaciones 100000147984  ==  [(0,316228)]

Comprobar con QuickCheck que un número natural n se puede representar como suma de dos cuadrados si, y sólo si, en la factorización prima de n todos los exponentes de sus factores primos congruentes con 3 módulo 4 son pares.


Leer más…

Factorizaciones de números de Hilbert

Un número de Hilbert es un entero positivo de la forma 4n+1. Los primeros números de Hilbert son 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, ...

Un primo de Hilbert es un número de Hilbert n que no es divisible por ningún número de Hilbert menor que n (salvo el 1). Los primeros primos de Hilbert son 5, 9, 13, 17, 21, 29, 33, 37, 41, 49, 53, 57, 61, 69, 73, 77, 89, 93, 97, 101, 109, 113, 121, 129, 133, 137, ...

Definir la función

factorizacionesH :: Integer -> [[Integer]]

tal que (factorizacionesH n) es la listas de primos de Hilbert cuyo producto es el número de Hilbert n. Por ejemplo,

factorizacionesH  25  ==  [[5,5]]
factorizacionesH  45  ==  [[5,9]]
factorizacionesH 441  ==  [[9,49],[21,21]]

Comprobar con QuickCheck que todos los números de Hilbert son factorizables como producto de primos de Hilbert (aunque laa factorización, como para el 441, puede no ser única).


Leer más…

Números primos de Hilbert.

Un número de Hilbert es un entero positivo de la forma 4n+1. Los primeros números de Hilbert son 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, ...

Un primo de Hilbert es un número de Hilbert n que no es divisible por ningún número de Hilbert menor que n (salvo el 1). Los primeros primos de Hilbert son 5, 9, 13, 17, 21, 29, 33, 37, 41, 49, 53, 57, 61, 69, 73, 77, 89, 93, 97, 101, 109, 113, 121, 129, 133, 137, ...

Definir la sucesión

primosH :: [Integer]

tal que sus elementos son los primos de Hilbert. Por ejemplo,

take 15 primosH  == [5,9,13,17,21,29,33,37,41,49,53,57,61,69,73]
primosH !! 20000 == 203221

Leer más…

La sucesión de Thue-Morse

La serie de Thue-Morse comienza con el término [0] y sus siguientes términos se construyen añadiéndole al anterior su complementario. Los primeros términos de la serie son

[0]
[0,1]
[0,1,1,0]
[0,1,1,0,1,0,0,1]
[0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0]

De esta forma se va formando una sucesión

0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,...

que se conoce como la sucesión de Thue-Morse.

Definir la sucesión

sucThueMorse :: [Int]

cuyos elementos son los de la sucesión de Thue-Morse. Por ejemplo,

λ> take 30 sucThueMorse
[0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0]
λ> map (sucThueMorse4 !!) [1234567..1234596]
[1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0]
λ> map (sucThueMorse4 !!) [4000000..4000030]
[1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1]

Comprobar con QuickCheck que si s(n) representa el término n-ésimo de la sucesión de Thue-Morse, entonces

s(2n)   = s(n)
s(2n+1) = 1 - s(n)

Leer más…

Ordenación por frecuencia

Definir la función

ordPorFrecuencia :: Ord a => [a] -> [a]

tal que (ordPorFrecuencia xs) es la lista obtenidas ordenando los elementos de xs por su frecuencia, de los que aparecen menos a los que aparecen más. Por ejemplo,

ordPorFrecuencia "canalDePanama"  ==  "DPcelmnnaaaaa"
ordPorFrecuencia "20012016"       ==  "61122000"

Leer más…

El algoritmo binario del mcd

El máximo común divisor (mcd) de dos números enteros no negativos se puede calcular mediante un algoritmo binario basado en las siguientes propiedades:

  1. Si a,b son pares, entonces mcd(a,b) = 2*mcd(a/2,b/2)
  2. Si a es par y b impar, entonces mcd(a,b) = mcd(a/2,b)
  3. Si a es impar y b par, entonces mcd(a,b) = mcd(a,b/2)
  4. Si a y b son impares y a > b, entonces mcd(a,b) = mcd((a-b)/2,b)
  5. Si a y b son impares y a < b, entonces mcd(a,b) = mcd(a,(b-a)/2)
  6. mcd(a,0) = a
  7. mcd(0,b) = b
  8. mcd(a,a) = a

Por ejemplo, el cálculo del mcd(660,420) es

mcd(660,420)
= 2*mcd(330,210)    [por 1]
= 2*2*mcd(165,105)  [por 1]
= 2*2*mcd(30,105)   [por 4]
= 2*2*mcd(15,105)   [por 2]
= 2*2*mcd(15,45)    [por 4]
= 2*2*mcd(15,15)    [por 4]
= 2*2*15            [por 8]
= 60

Definir la función

mcd :: Integer -> Integer -> Integer

Definir la función

tal que (mcd a b) es el máximo común divisor de a y b calculado mediante el algoritmo binario del mcd. Por ejemplo,

mcd 660 420  ==  60
mcd 3 0      ==  3
mcd 0 3      ==  3

Comprobar con QuickCheck que, para los enteros no negativos, las funciones mcd y gcd son equivalentes.


Leer más…

Agrupamiento por propiedad

Definir la función

agrupa :: (a -> Bool) -> [a] -> [[a]]

tal que (agrupa p xs) es la lista obtenida separando los elementos consecutivos de xs que verifican la propiedad p de los que no la verifican. Por ejemplo,

agrupa odd   [1,2,0,4,9,6,4,5,7,2]  ==  [[1],[2,0,4],[9],[6,4],[5,7],[2]]
agrupa even  [1,2,0,4,9,6,4,5,7,2]  ==  [[],[1],[2,0,4],[9],[6,4],[5,7],[2]]
agrupa (> 4) [1,2,0,4,9,6,4,5,7,2]  ==  [[],[1,2,0,4],[9,6],[4],[5,7],[2]]
agrupa (< 4) [1,2,0,4,9,6,4,5,7,2]  ==  [[1,2,0],[4,9,6,4,5,7],[2]]

Comprobar con QuickCheck que para cualquier propiedad p y cualquier lista xs, la concatenación de (agrupa p xs) es xs; es decir,

prop_agrupa :: Blind (Int -> Bool) -> [Int] -> Bool
prop_agrupa (Blind p) xs =
    concat (agrupa1 p xs) == xs

Nota. Usar la librería Test.QuickCheck.Modifiers.


Leer más…

Sumas de dos primos

Definir la sucesión

sumasDeDosPrimos :: [Integer]

cuyos elementos son los números que se pueden escribir como suma de dos números primos. Por ejemplo,

λ> take 23 sumasDeDosPrimos
[4,5,6,7,8,9,10,12,13,14,15,16,18,19,20,21,22,24,25,26,28,30,31]

Leer más…

De árboles a listas

Los árboles binarios con datos en nodos y hojas se definen por

data Arbol a = H a | N a (Arbol a) (Arbol a) deriving Show

Por ejemplo, el árbol

       3
      / \
     /   \
    4     7
   / \   / \
  5   0 0   3
 / \
2   0

se representa por

ejArbol :: Arbol Integer
ejArbol = N 3 (N 4 (N 5 (H 2)(H 0)) (H 0)) (N 7 (H 0) (H 3))

Definir la función

sucesores :: Arbol a -> [(a,[a])]

tal que (sucesores t) es la lista de los pares formados por los elementos del árbol t junto con sus sucesores. Por ejemplo,

λ> sucesores ejArbol
[(3,[4,7]),(4,[5,0]),(5,[2,0]),(2,[]),(0,[]),(0,[]),
 (7,[0,3]),(0,[]),(3,[])]

Leer más…

Conjunto de funciones

Una función f entre dos conjuntos A e B se puede representar mediante una lista de pares de AxB tales que para cada elemento a de A existe un único elemento b de B tal que (a,b) pertenece a f. Por ejemplo,

  • [(1,2),(3,6)] es una función de [1,3] en [2,4,6];
  • [(1,2)] no es una función de [1,3] en [2,4,6], porque no tiene ningún par cuyo primer elemento sea igual a 3;
  • [(1,2),(3,6),(1,4)] no es una función porque hay dos pares distintos cuya primera coordenada es 1.

Definir la función

funciones :: [a] -> [a] -> [[(a,a)]]

tal que (funciones xs ys) es el conjunto de las funciones de xs en ys. Por ejemplo,

λ> funciones [] [2,4,6]
[[]]
λ> funciones [3] [2,4,6]
[[(3,2)],[(3,4)],[(3,6)]]
λ> funciones [1,3] [2,4,6]
[[(1,2),(3,2)], [(1,2),(3,4)], [(1,2),(3,6)], [(1,4),(3,2)], [(1,4),(3,4)],
 [(1,4),(3,6)], [(1,6),(3,2)], [(1,6),(3,4)], [(1,6),(3,6)]]

Comprobar con QuickCheck que si xs es un conjunto con n elementos e ys un conjunto con m elementos, entonces (funciones xs ys) tiene m^n elementos.

Nota. Al hacer la comprobación limitar el tamaño de las pruebas como se indica a continuación

λ> quickCheckWith (stdArgs {maxSize=7}) prop_funciones
+++ OK, passed 100 tests.

Leer más…

Serie de Thue-Morse

La serie de Thue-Morse comienza con el término [0] y sus siguientes términos se construyen añadiéndole al anterior su complementario. Los primeros términos de la serie son

[0]
[0,1]
[0,1,1,0]
[0,1,1,0,1,0,0,1]
[0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0]

Definir la lista

serieThueMorse :: [[Integer]]

tal que sus elementos son los términos de la serie de Thue-Morse. Por ejemplo,

λ> take 4 serieThueMorse
[[0],[0,1],[0,1,1,0],[0,1,1,0,1,0,0,1]]

Comprobar con QuickCheck que cada término de la serie de Thue-Morse se obtiene del anterior sustituyendo los 1 por 1, 0 y los 0 por 0, 1.


Leer más…

Sumas digitales de primos consecutivos

Definir la función

primosConsecutivosConSumasDigitalesPrimas :: Int -> [[Integer]]

tal que (primosConsecutivosConSumasDigitalesPrimas k) es la sucesión de lista de k primos consecutivos tales que las sumas ordenadas de sus dígitos también son primos consecutivos. Por ejemplo,

λ> take 5 (primosConsecutivosConSumasDigitalesPrimas 2)
[[2,3],[3,5],[5,7],[41,43],[43,47]]
λ> take 5 (primosConsecutivosConSumasDigitalesPrimas 3)
[[2,3,5],[3,5,7],[41,43,47],[191,193,197],[193,197,199]]
λ> take 4 (primosConsecutivosConSumasDigitalesPrimas 4)
[[2,3,5,7],[3,5,7,11],[191,193,197,199],[821,823,827,829]]
λ> primosConsecutivosConSumasDigitalesPrimas 4 !! 50
[129197,129209,129221,129223]

Leer más…

Números belgas

Un número n es k-belga si la sucesión cuyo primer elemento es k y cuyos elementos se obtienen sumando reiteradamente las cifras de n contiene a n. Por ejemplo,

  • El 18 es 0-belga, porque a partir del 0 vamos a ir sumando sucesivamente 1, 8, 1, 8, ... hasta llegar o sobrepasar el 18: 0, 1, 9, 10, 18, ... Como se alcanza el 18, resulta que el 18 es 0-belga.
  • El 19 no es 1-belga, porque a partir del 1 vamos a ir sumando sucesivamente 1, 8, 1, 8, ... hasta llegar o sobrepasar el 18: 0, 1, 10, 11, 20, 21, ... Como no se alcanza el 19, resulta que el 19 no es 1-belga.

Definir la función

esBelga :: Int -> Int -> Bool

tal que (esBelga k n) se verifica si n es k-belga. Por ejemplo,

esBelga 0 18                              ==  True
esBelga 1 19                              ==  False
esBelga 0 2016                            ==  True
[x | x <- [0..30], esBelga 7 x]           ==  [7,10,11,21,27,29]
[x | x <- [0..30], esBelga 10 x]          ==  [10,11,20,21,22,24,26]
length [n | n <- [1..9000], esBelga 0 n]  ==  2857

Comprobar con QuickCheck que para todo número entero positivo n, si k es el resto de n entre la suma de los dígitos de n, entonces n es k-belga.


Leer más…

Antiimágenes en una función creciente

Definir la función

antiimagen :: (Int -> Int) -> Int -> Maybe Int

tal que (antiimagen f y) es justo el x tal que f(x) = y, si y pertenece a la imagen de la función creciente f, o nada, en caso contrario. Por ejemplo,

antiimagen (^2) 25  ==  Just 5
antiimagen (^3) 25  ==  Nothing

Nota. Se supone que f está definida sobre los números naturales.


Leer más…

Relleno de matrices

Dada una matriz cuyos elementos son 0 ó 1, su relleno es la matriz obtenida haciendo iguales a 1 los elementos de las filas y de las columna que contienen algún uno. Por ejemplo, el relleno de la matriz de la izquierda es la de la derecha:

0 0 0 0 0    1 0 0 1 0
0 0 0 0 0    1 0 0 1 0
0 0 0 1 0    1 1 1 1 1
1 0 0 0 0    1 1 1 1 1
0 0 0 0 0    1 0 0 1 0

Las matrices se pueden representar mediante tablas cuyos índices son pares de enteros

type Matriz = Array (Int,Int) Int

por ejemplo, la matriz de la izquierda de la figura anterior se define por

ej :: Matriz
ej = listArray ((1,1),(5,5)) [0, 0, 0, 0, 0,
                              0, 0, 0, 0, 0,
                              0, 0, 0, 1, 0,
                              1, 0, 0, 0, 0,
                              0, 0, 0, 0, 0]

Definir la función

relleno :: Matriz -> Matriz

tal que (relleno p) es el relleno de la matriz p. Por ejemplo,

λ> elems (relleno ej)
[1,0,0,1,0,
 1,0,0,1,0,
 1,1,1,1,1,
 1,1,1,1,1,
 1,0,0,1,0]

Leer más…

Huecos maximales entre primos

El hueco de un número primo p es la distancia entre p y primo siguiente de p. Por ejemplo, el hueco de 7 es 4 porque el primo siguiente de 7 es 11 y 4 = 11-7. Los huecos de los primeros números son

Primo Hueco
 2    1
 3    2
 7    4
11    2

El hueco de un número primo p es maximal si es mayor que los huecos de todos los números menores que p. Por ejemplo, 4 es un hueco maximal de 7 ya que los huecos de los primos menores que 7 son 1 y 2 y ambos son menores que 4. La tabla de los primeros huecos maximales es

Primo Hueco
  2    1
  3    2
  7    4
 23    6
 89    8
113   14
523   18
887   20

Definir la sucesión

primosYhuecosMaximales :: [(Integer,Integer)]

cuyos elementos son los números primos con huecos maximales junto son sus huecos. Por ejemplo,

λ> take 8 primosYhuecosMaximales
[(2,1),(3,2),(7,4),(23,6),(89,8),(113,14),(523,18),(887,20)]
λ> primosYhuecosMaximales !! 20
(2010733,148)

Leer más…

Lista tautológica de literales

En lógica matemática, un literal es una fórmula atómica o su negación. Se puede definir por el tipo de dato

data Literal = Atom String
             | Neg Literal
             deriving (Eq, Show)

Por ejemplo, el literal los literales p y ¬q se representan por las expresiones (Atom "p") y (Neg (Atom "q")), respectivamente.

Una lista de literales (que se interpreta como su disyunción) es un tautología si contiene a una fórmula atómica y su negación.

Definir la función

tautologia :: [Literal] -> Bool

tal que (tautologia xs) se verifica si la lista de literales xs es una tautología. Por ejemplo,

λ> tautologia [Atom "p", Neg (Atom "q"), Neg (Atom "p")]
True
λ> tautologia [Atom "p", Neg (Atom "q"), Neg (Atom "r")]
False
λ> tautologia [Atom "p", Neg (Atom "q"), Neg (Atom "q")]
False

Leer más…

Puntos visibles en la cuadrícula de un plano

La cuadrícula entera de lado n, Cₙ, es el conjunto de los puntos (x,y) donde x e y son números enteros tales que 1 ≤ x, y ≤ n.

Un punto (x,y) de Cₙ es visible desde el origen si el máximo común divisor de x e y es 1. Por ejemplo, el punto (4,6) no es visible porque está ocultado por el (2,3); en cambio, el (2,3) sí es visible.

El conjunto de los puntos visibles en la cuadrícula entera de lado 6 son (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (2,1), (2,3), (2,5), (3,1), (3,2), (3,4), (3,5), (4,1), (4,3), (4,5), (5,1), (5,2), (5,3), (5,4), (5,6), (6,1) y (6,5).

Definir la función

nVisibles :: Integer -> Integer

tal que (nVisibles n) es el número de los puntos visibles en la cuadrícula de lado n.Por ejemplo,

nVisibles 6       ==  23
nVisibles 10      ==  63
nVisibles 100     ==  6087
nVisibles 1000    ==  608383
nVisibles 10000   ==  60794971
nVisibles 100000  ==  6079301507

Leer más…

Cambios de signo

En una lista xs se produce un cambio de signo por cada elemento x de la lista junto el primero de los elementos de xs con signo opuesto al de x. Por ejemplo,en la lista [6,5,-4,0,-2,-7,0,-8,-1,4] hay 2 cambios de signo (entre (5,-4) y (-1,4)) y en la lista [6,5,-4,0, 2,-7,0,-8,-1,4] hay 4 cambios de signo (entre (5,-4), (-4,2), (2,-7) y(-1,4)).

Definir la función

nCambios :: (Num a, Ord a) => [a] -> Int

tal que (nCambios xs) es el número de cambios de signos de la lista xs. Por ejemplo,

nCambios []                          ==  0
nCambios [6,5,-4,0,-2,-7,0,-8,-1,4]  ==  2
nCambios [6,5,-4,0, 2,-7,0,-8,-1,4]  ==  4

Leer más…

Parte libre de cuadrados y parte cuadrada de un número

La parte libre de cuadrados de un número n es el producto de todos sus divisores primos con exponente impar en la factorización prima de n. Por ejemplo, la parte libre de cuadrados de 360 es 10 ya que 360 = 2³3²5 y 2.5 = 10; además, 360 = 10.6²

La parte cuadrada de un número n es el mayor número cuadrado que divide a n. Por ejemplo, la parte cuadrada de 360 es 6.

Definir las funciones

parteLibre    :: Integer -> Integer
parteCuadrada :: Integer -> Integer

tales que

  • (parteLibre x) es la parte libre de x. Por ejemplo,
parteLibre 360                 ==  10
parteLibre 1800                ==  2
[parteLibre n | n <- [1..14]]  ==  [1,2,3,1,5,6,7,2,1,10,11,3,13,14]
  • (parteCuadrada x) es la parte cuadrada de x. Por ejemplo,
parteCuadrada 360                 ==  36
parteCuadrada 1800                ==  900
[parteCuadrada n | n <- [1..14]]  ==  [1,1,1,4,1,1,1,4,9,1,1,4,1,1]

Leer más…

La función indicatriz de Euler

La indicatriz de Euler (también llamada función φ de Euler) es una función importante en teoría de números. Si n es un entero positivo, entonces φ(n) se define como el número de enteros positivos menores o iguales a n y coprimos con n. Por ejemplo, φ(36) = 12 ya que los números menores o iguales a 36 y coprimos con 36 son doce: 1, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, y 35.

Definir la función

phi :: Integer -> Integer

tal que (phi n) es igual a φ(n). Por ejemplo,

phi 36                     ==  12
map phi [10..20]           ==  [4,10,4,12,6,8,8,16,6,18,8]
phi (3^10^5) `mod` (10^9)  ==  681333334

Comprobar con QuickCheck que, para todo n > 0, φ(10ⁿ) tiene n dígitos.


Leer más…

Fórmula dual

Las fórmulas proposicionales construidas con las constantes verdadero (⊤), falso (⊥), las variables proposicionales y las conectivas de negación (¬), conjunción (∧) y disyunción (∨) se pueden definir usando el siguiente tipo de datos

data Prop = Const Bool
          | Var Char
          | Neg Prop
          | Conj Prop Prop
          | Disj Prop Prop
          deriving (Eq, Show)

Por ejemplo, la fórmula (A ∧ ⊥) ∨ (⊤ ∧ B) se representa por

Disj (Conj (Var 'A') (Const False)) (Conj (Const True) (Var 'B'))

La fórmula dual de una fórmula p es la fórmula obtenida intercambiando en p las ∧ por ∨ y también las ⊤ por ⊥. Por ejemplo, la dual de (A ∧ ⊥) ∨ (⊤ ∧ B) es (A ∨ ⊤) ∧ (⊥ ∨ B)

Definir la función

dual :: Prop -> Prop

tal que (dual p) es la dual de p. Por ejemplo,

λ> dual (Disj (Conj (Var 'A') (Const False)) (Conj (Const True) (Var 'B')))
Conj (Disj (Var 'A') (Const True)) (Disj (Const False) (Var 'B'))

Leer más…

Sucesión de suma de cuadrados de los dígitos

Definir la función

sucSumaCuadradosDigitos :: Integer -> [Integer]

tal que (sucSumaCuadradosDigitos n) es la sucesión cuyo primer término es n y los restantes se obtienen sumando los cuadrados de los dígitos de su término anterior. Por ejemplo,

λ> take 20 (sucSumaCuadradosDigitos 2016)
[2016,41,17,50,25,29,85,89,145,42,20,4,16,37,58,89,145,42,20,4]
λ> take 20 (sucSumaCuadradosDigitos 1976)
[1976,167,86,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
λ> sucSumaCuadradosDigitos 2016 !! (10^8)
145

Leer más…

Puntos en una región

Definir la función

puntos :: Integer -> [(Integer,Integer)]

tal que (puntos n) es la lista de los puntos (x,y) con coordenadas enteras de la cuadrícula [1..n]x[1..n] (es decir, 1 ≤ x,y ≤ n) tales que |x²-xy-y²| = 1. Por ejemplo,

length (puntos 10)          ==  5
length (puntos 100)         ==  10
length (puntos 1000)        ==  15
length (puntos (10^50000))  ==  239249

Leer más…

2016 es un número práctico

Un entero positivo n es un número práctico si todos los enteros positivos menores que él se pueden expresar como suma de distintos divisores de n. Por ejemplo, el 12 es un número práctico, ya que todos los enteros positivos menores que 12 se pueden expresar como suma de divisores de 12 (1, 2, 3, 4 y 6) sin usar ningún divisor más de una vez en cada suma:

 1 = 1
 2 = 2
 3 = 3
 4 = 4
 5 = 2 + 3
 6 = 6
 7 = 1 + 6
 8 = 2 + 6
 9 = 3 + 6
10 = 4 + 6
11 = 1 + 4 + 6

En cambio, 14 no es un número práctico ya que 6 no se puede escribir como suma, con sumandos distintos, de divisores de 14.

Definir la función

esPractico :: Integer -> Bool

tal que (esPractico n) se verifica si n es un número práctico. Por ejemplo,

esPractico 12                                      ==  True
esPractico 14                                      ==  False
esPractico 2016                                    ==  True
esPractico 42535295865117307932921825928971026432  ==  True

Leer más…

Suma con redondeos

Definir las funciones

sumaRedondeos       :: Integer -> [Integer]
limiteSumaRedondeos :: Integer -> Integer

tales que

  • (sumaRedondeos n) es la sucesión cuyo k-ésimo término es
redondeo (n/2) + redondeo (n/4) + ... + redondeo (n/2^k)

Por ejemplo,

take 5 (sumaRedondeos 1000)  ==  [500,750,875,937,968]
  • (limiteSumaRedondeos n) es la suma de la serie
redondeo (n/2) + redondeo (n/4) + redondeo (n/8) + ...

Por ejemplo,

limiteSumaRedondeos1 2000                    ==  1999
limiteSumaRedondeos1 2016                    ==  2016
limiteSumaRedondeos5 (10^308) `mod` (10^10)  ==  123839487

Leer más…

Elementos óptimos

Definir la función

optimos :: Eq b => (b -> b -> Bool) -> (a -> b) -> [a] -> [a]

tal que (optimos r f xs) es la lista de los elementos de xs donde la función f alcanza sus valores óptimos respecto de la relación r. Por ejemplo,

optimos (<) length ["ab","c","de","f"]  ==  ["c","f"]
optimos (>) length ["ab","c","de","f"]  ==  ["ab","de"]

Leer más…

Elementos maximales

Definir la función

maximales :: Eq a => (a -> a -> Bool) -> [a] -> [a]

tal que (maximales r xs) es la lista de los elementos de xs para los que no hay ningún otro elemento de xs mayor según la relación r. Por ejemplo,

maximales (>) [2,3,4,6]                     ==  [6]
maximales (<) [2,3,4,6]                     ==  [2]
maximales (\x y -> mod x y == 0) [2,3,4,6]  ==  [4,6]
maximales (\x y -> mod y x == 0) [2,3,4,6]  ==  [2,3]

Leer más…

Reconocimiento de anterior

Definir la función

esAnterior :: Eq a => [a] -> a -> a -> Bool

tal que (esAnterior xs y z) se verifica si y ocurre en xs antes que z (que puede no pertenecer a xs). Por ejemplo,

esAnterior [1,3,7,2] 3 2  ==  True
esAnterior [1,3,7,2] 3 1  ==  False
esAnterior [1,3,7,2] 3 5  ==  True
esAnterior [1,3,7,2] 5 3  ==  False

Leer más…

Operación sobre todos los pares

Definir la función

todosPares :: (a -> b -> c) -> [a] -> [b] -> [c]

tal que (todosPares f xs ys) es el resultado de aplicar la operación f a todos los pares de xs e ys. Por ejemplo,

todosPares (*) [2,3,5] [7,11]            == [14,22,21,33,35,55]
todosPares (\x y -> x:show y) "ab" [7,5] == ["a7","a5","b7","b5"]

Leer más…

Inserciones por posición

Definir la función

inserta :: [a] -> [[a]] -> [[a]]

tal que (inserta xs yss) es la lista obtenida insertando

  • el primer elemento de xs como primero en la primera lista de yss,
  • el segundo elemento de xs como segundo en la segunda lista de yss (si la segunda lista de yss tiene al menos un elemento),
  • el tercer elemento de xs como tercero en la tercera lista de yss (si la tercera lista de yss tiene al menos dos elementos),

y así sucesivamente. Por ejemplo,

inserta [1,2,3] [[4,7],[6],[9,5,8]]  ==  [[1,4,7],[6,2],[9,5,3,8]]
inserta [1,2,3] [[4,7],[] ,[9,5,8]]  ==  [[1,4,7],[],   [9,5,3,8]]
inserta [1,2]   [[4,7],[6],[9,5,8]]  ==  [[1,4,7],[6,2],[9,5,8]]
inserta [1,2,3] [[4,7],[6]]          ==  [[1,4,7],[6,2]]
inserta "tad"   ["odo","pra","naa"]  ==  ["todo","para","nada"]

Leer más…

Árbol de Navidad

Definir el procedimiento

arbol :: Int -> IO ()

tal que (arbol n) dibuja el árbol de Navidad con una copa de altura n y un tronco de altura la mitad de n. Por ejemplo,

λ> arbol 5

     X
    XXX
   XXXXX
  XXXXXXX
 XXXXXXXXX
     X
     X

λ> arbol 6

      X
     XXX
    XXXXX
   XXXXXXX
  XXXXXXXXX
 XXXXXXXXXXX
      X
      X
      X

λ> arbol 7

       X
      XXX
     XXXXX
    XXXXXXX
   XXXXXXXXX
  XXXXXXXXXXX
 XXXXXXXXXXXXX
       X
       X
       X

Leer más…

Siembra de listas

Definir la función

siembra :: [Int] -> [Int]

tal que (siembra xs) es la lista ys obtenida al repartir cada elemento x de la lista xs poniendo un 1 en las x siguientes posiciones de la lista ys. Por ejemplo,

siembra [4]      ==  [0,1,1,1,1]
siembra [0,2]    ==  [0,0,1,1]
siembra [4,2]    ==  [0,1,2,2,1]

El tercer ejemplo se obtiene sumando la siembra de 4 en la posición 0 (como el ejemplo 1) y el 2 en la posición 1 (como el ejemplo 2). Otros ejemplos son

siembra [0,4,2]          ==  [0,0,1,2,2,1]
siembra [3]              ==  [0,1,1,1]
siembra [3,4,2]          ==  [0,1,2,3,2,1]
siembra [3,2,1]          ==  [0,1,2,3]
sum $ siembra [1..2500]  ==  3126250

Comprobar con QuickCheck que la suma de los elementos de (siembra xs) es igual que la suma de los de xs.

Nota: Se supone que el argumento es una lista de números no negativos y que se puede ampliar tanto como sea necesario para repartir los elementos.


Leer más…

Producto infinito

Definir la función

productoInfinito :: [Int] -> [Int]

tal que (productoInfinito xs) es la lista infinita que en la posición N tiene el producto de los N primeros elementos de la lista infinita xs. Por ejemplo,

take 5 (productoInfinito [1..])    ==  [1,2,6,24,120]
take 5 (productoInfinito [2,4..])  ==  [2,8,48,384,3840]
take 5 (productoInfinito [1,3..])  ==  [1,3,15,105,945]

Nota: Este ejercicio es parte del examen del grupo 3 del 2 de diciembre.


Leer más…

Listas hermanadas

Una lista hermanada es una lista de números estrictamente positivos en la que cada elemento tiene algún factor primo en común con el siguiente, en caso de que exista, o alguno de los dos es un 1. Por ejemplo,

  • [2,6,3,9,1,5] es una lista hermanada pues 2 y 6 tienen un factor en común (2); 6 y 3 tienen un factor en común (3); 3 y 9 tienen un factor en común (3); de 9 y 1 uno es el número 1; y de 1 y 5 uno es el número 1.
  • [2,3,5] no es una lista hermanada pues 2 y 3 no tienen ningún factor primo en común.

Definir la función

hermanada :: [Int] -> Bool

tal que (hermanada xs) se verifica si la lista xs es hermanada según la definición anterior. Por ejemplo,

hermanada [2,6,3,9,1,5]   ==  True
hermanada [2,3,5]         ==  False
hermanada [2,4..1000000]  ==  True

Nota: Este ejercicio es parte del examen del grupo 3 del 2 de diciembre.


Leer más…

Potencias perfectas

Un número natural n es una potencia perfecta si existen dos números naturales m > 1 y k > 1 tales que n = m^k. Las primeras potencias perfectas son

4 = 2², 8 = 2³, 9 = 3², 16 = 2, 25 = 5², 27 = 3³, 32 = 2,
36 = 6², 49 = 7², 64 = 2, ...

Definir la sucesión

potenciasPerfectas :: [Integer]

cuyos términos son las potencias perfectas. Por ejemplo,

take 10 potenciasPerfectas  ==  [4,8,9,16,25,27,32,36,49,64]
potenciasPerfectas !! 100   ==  6724

Definir el procedimiento

grafica :: Int -> IO ()

tal que (grafica n) es la representación gráfica de las n primeras potencias perfectas. Por ejemplo, para (grafica 30) dibuja

!Potencias perfectas](/images/Potencias_perfectas.png)


Leer más…

Factorizable respecto de una lista

Definir la función

factorizable :: Integer -> [Integer] -> Bool

tal que (factorizable x ys) se verifica si x se puede escribir como producto de potencias de elementos de ys. Por ejemplo,

factorizable 1  [2,5,6]                           ==  True
factorizable 12 [2,5,3]                           ==  True
factorizable 12 [2,5,6]                           ==  True
factorizable 12 [7,5,12]                          ==  True
factorizable 12 [2,3,1]                           ==  True
factorizable 12 [2,3,0]                           ==  True
factorizable 24 [12,4,6]                          ==  True
factorizable 0  [2,3,0]                           ==  True
factorizable 12 [5,6]                             ==  False
factorizable 12 [2,5,1]                           ==  False
factorizable 0  [2,3,5]                           ==  False
factorizable (product [1..3000])     [1..100000]  ==  True
factorizable (1 + product [1..3000]) [1..100000]  ==  False

Leer más…

Año cúbico

El año 2016 será un año cúbico porque se puede escribir como la suma de los cubos de 7 números consecutivos; en efecto,

2016 = 3³+ 4³ +...+ 9³

Definir la función

esCubico :: Integer -> Bool

tal que (esCubico x) se verifica si x se puede escribir como la suma de los cubos de 7 números consecutivos. Por ejemplo,

esCubico 2016                ==  True
esCubico 2017                ==  False
esCubico 189005670081900441  ==  True
esCubico 189005670081900442  ==  False

Leer más…

Primos con cubos

Un primo con cubo es un número primo p para el que existe algún entero positivo n tal que la expresión n³ + n²p es un cubo perfecto. Por ejemplo, 19 es un primo con cubo ya que 8³ + 8²×19 = 12³.

Definir la sucesión

primosConCubos :: [Integer]

tal que sus elementos son los primos con cubo. Por ejemplo,

λ> take 6 primosConCubos
[7,19,37,61,127,271]
λ> length (takeWhile (< 1000000) primosConCubos)
173

Leer más…

Primos cubanos

Un primo cubano es un número primo que se puede escribir como diferencia de dos cubos consecutivos. Por ejemplo, el 61 es un primo cubano porque es primo y 61 = 5³-4³.

Definir la sucesión

cubanos :: [Integer]

tal que sus elementos son los números cubanos. Por ejemplo,

λ> take 15 cubanos
[7,19,37,61,127,271,331,397,547,631,919,1657,1801,1951,2269]

Leer más…

Clausura transitiva de una relación binaria

La clausura transitiva de una relación binaria R es la menor relación transitiva que contiene a R. Se puede calcular usando la composición de relaciones. Veamos un ejemplo, en el que (R ∘ S) representa la composición de R y S (definida en el ejercicio del lunes): sea

R = [(1,2),(2,5),(5,6)]

la relación R no es transitiva ya que (1,2) y (1,5) pertenecen a R pero (1,5) no pertenece; sea

R1 = R ∪ (R ∘ R)
= [(1,2),(2,5),(5,6),(1,5),(2,6)]

la relación R1 tampoco es transitiva ya que (1,2) y (2,6) pertenecen a R pero (1,6) no pertenece; sea

R2 = R1 ∪ (R1 ∘ R1)
= [(1,2),(2,5),(5,6),(1,5),(2,6),(1,6)]

La relación R2 es transitiva y contiene a R. Además, R2 es la clausura transitiva de R.

Definir la función

clausuraTransitiva :: Eq a => Rel a -> Rel a

tal que (clausuraTransitiva r) es la clausura transitiva de r. Por ejemplo,

λ> clausuraTransitiva [(1,2),(2,5),(5,6)]
[(1,2),(2,5),(5,6),(1,5),(2,6),(1,6)]
λ> clausuraTransitiva [(1,2),(2,5),(5,6),(6,3)]
[(1,2),(2,5),(5,6),(6,3),(1,5),(2,6),(5,3),(1,6),(2,3),(1,3)]

Leer más…

Transitividad de una relación

Una relación binaria R sobre un conjunto A es transitiva cuando se cumple que siempre que un elemento se relaciona con otro y éste último con un tercero, entonces el primero se relaciona con el

Definir la función

transitiva :: Eq a => [(a,a)] -> Bool

tal que (transitiva r) se verifica si la relación r es transitiva. Por ejemplo,

transitiva [(1,1),(1,3),(3,1),(3,3),(5,5)]  ==  True
transitiva [(1,1),(1,3),(3,1),(5,5)]        ==  False

Leer más…

Composición de relaciones binarias

Las relaciones binarias en un conjunto A se pueden representar mediante conjuntos de pares de elementos de A. Por ejemplo, la relación de divisibilidad en el conjunto {1,2,3,6} se representa por

[(1,1),(1,2),(1,3),(1,6),(2,2),(2,6),(3,3),(3,6),(6,6)]

La composición de dos relaciones binarias R y S en el conjunto A es la relación binaria formada por los pares (x,y) para los que existe un z tal que (x,z) ∈ R y (z,y) ∈ S.

Definir la función

composicion :: Eq a => [(a,a)] -> [(a,a)] -> [(a,a)]

tal que (composicion r s) es la composición de las relaciones binarias r y s. Por ejemplo,

λ> composicion [(1,2)] [(2,3),(2,4)]
[(1,3),(1,4)]
λ> composicion [(1,2),(5,2)] [(2,3),(2,4)]
[(1,3),(1,4),(5,3),(5,4)]
λ> composicion [(1,2),(1,4),(1,5)] [(2,3),(4,3)]
[(1,3)]
λ> composicion [(0,1)] [(2,3)]
[]

Nota: Se supone que las relaciones binarias son listas sin elementos repetidos.


Leer más…

Los números de Smith

Un número de Smith es un número natural compuesto que cumple que la suma de sus dígitos es igual a la suma de los dígitos de todos sus factores primos (si tenemos algún factor primo repetido lo sumamos tantas veces como aparezca). Por ejemplo, el 22 es un número de Smith ya que

22  = 2*11 y
2+2 = 2+(1+1)

y el 4937775 también lo es ya que

4937775       = 3*5*5*65837 y
4+9+3+7+7+7+5 = 3+5+5+(6+5+8+3+7)

Definir las funciones

esSmith :: Integer -> Bool
smith :: [Integer]

tales que

  • (esSmith x) se verifica si x es un número de Smith. Por ejemplo,
esSmith 22          ==  True
esSmith 29          ==  False
esSmith 2015        ==  False
esSmith 4937775     ==  True
esSmith 4567597056  ==  True
  • smith es la lista cuyos elementos son los números de Smith. Por ejemplo,
λ> take 17 smith
[4,22,27,58,85,94,121,166,202,265,274,319,346,355,378,382,391]
λ> smith !! 2000
62158

Leer más…

Números de Armstrong

Un número de n dígitos es un número de Armstrong si es igual a la suma de las n-ésimas potencias de sus dígitos. Por ejemplo, 371, 8208 y 4210818 son números de Armstrong ya que

    371 = 3^3 + 7^3 + 1^3
   8208 = 8^4 + 2^4 + 0^4 + 8^4
4210818 = 4^7 + 2^7 + 1^7 + 0^7 + 8^7 + 1^7 + 8^7

Definir las funciones

esArmstrong :: Integer -> Bool
armstrong :: [Integer]

tales que

  • (esArmstrong x) se verifica si x es un número de Armstrong. Por ejemplo,
esArmstrong 371                                      ==  True
esArmstrong 8208                                     ==  True
esArmstrong 4210818                                  ==  True
esArmstrong 2015                                     ==  False
esArmstrong 115132219018763992565095597973971522401  ==  True
esArmstrong 115132219018763992565095597973971522402  ==  False
  • armstrong es la lista cuyos elementos son los números de Armstrong. Por ejemplo,
λ> take 18 armstrong
[1,2,3,4,5,6,7,8,9,153,370,371,407,1634,8208,9474,54748,92727]

Comprobar con QuickCheck que los números mayores que 115132219018763992565095597973971522401 no son números de Armstrong.


Leer más…

Raíces enteras de los números primos

Definir la sucesión

raicesEnterasDePrimos :: [Integer]

cuyos elementos son las partes enteras de las raíces cuadradas de los números primos. Por ejemplo,

λ> take 30 raicesEnterasDePrimos
[1,1,2,2,3,3,4,4,4,5,5,6,6,6,6,7,7,7,8,8,8,8,9,9,9,10,10,10,10,10]
λ> raicesEnterasDePrimos !!  9963
322
λ> raicesEnterasDePrimos !!  9964
323

Comprobar con QuickCheck que la diferencia entre dos términos consecutivos de la sucesión es como máximo igual a 1.


Leer más…

Paridad de un árbol

Los árboles binarios con valores en las hojas y en los nodos se definen por

data Arbol a = H a
              | N a (Arbol a) (Arbol a)
              deriving Show

Por ejemplo, el árbol

     5
    / \
   /   \
  9     7
 / \   / \
1   4 6   8

se puede representar por

N 5 (N 9 (H 1) (H 4)) (N 7 (H 6) (H 8))

Decimos que un árbol binario es par si la mayoría de sus nodos son pares e impar en caso contrario.

Para representar la paridad se define el tipo Paridad

data Paridad = Par | Impar deriving (Eq, Show)

Definir la función

paridad :: Arbol3 Int -> Paridad

tal que (paridad a) es la paridad del árbol a. Por ejemplo,

paridad (N 8 (N 6 (H 3) (H 4)) (H 5))  ==  Par
paridad (N 8 (N 9 (H 3) (H 4)) (H 5))  ==  Impar

Leer más…

Separación y mezcla de listas

Definir las funciones

separacion :: [a] -> ([a],[a])
mezcla     :: ([a],[a]) -> [a]

tales que (separacion xs) es el par formado eligiendo alternativamente elementos de xs mientras que mezcla intercala los elementos de las dos listas. Por ejemplo,

separacion [1..5]                   ==  ([1,3,5],[2,4])
mezcla ([1,3,5],[2,4])              ==  [1,2,3,4,5]
separacion "Telescopio"             ==  ("Tlsoi","eecpo")
mezcla ("Tlsoi","eecpo")            ==  "Telescopio"
take 5 (fst (separacion [2,4..]))   ==  [2,6,10,14,18]
take 6 (mezcla ([2,4..],[7,14..]))  ==  [2,7,4,14,6,21]

Comprobar con QuickCheck que

mezcla (separacion xs) == xs

Leer más…

Particiones en k subconjuntos

Definir la función

particiones :: [a] -> Int -> [[[a]]]

tal que (particiones xs k) es la lista de las particiones de xs en k subconjuntos disjuntos. Por ejemplo,

λ> particiones [2,3,6] 2
[[[2],[3,6]],[[2,3],[6]],[[3],[2,6]]]
λ> particiones [2,3,6] 3
[[[2],[3],[6]]]
λ> particiones [4,2,3,6] 3
[[[4],[2],[3,6]],[[4],[2,3],[6]],[[4],[3],[2,6]],
 [[4,2],[3],[6]],[[2],[4,3],[6]],[[2],[3],[4,6]]]
λ> particiones [4,2,3,6] 1
[[[4,2,3,6]]]
λ> particiones [4,2,3,6] 4
[[[4],[2],[3],[6]]]

Leer más…

Repeticiones según la posición

Definir la función

transformada :: [a] -> [a]

tal que (transformada xs) es la lista obtenida repitiendo cada elemento tantas veces como indica su posición en la lista. Por ejemplo,

transformada [7,2,5] == [7,2,2,5,5,5]
transformada "eco"   == "eccooo"

Comprobar con QuickCheck si la transformada de una lista de n números enteros, con n >= 2, tiene menos de n^3 elementos.


Leer más…

Mayor semiprimo menor que n

Un número semiprimo es un número natural que es producto de dos números primos no necesariamente distintos. Por ejemplo, 26 es semiprimo (porque ' 26 = 2*13' ) y 49 también lo es (porque 49 = 7*7).

Definir la función

mayorSemiprimoMenor :: Integer -> Integer

tal que (mayorSemiprimoMenor n) es el mayor semiprimo menor que n (suponiendo que n > 4). Por ejemplo,

mayorSemiprimoMenor 27      ==  26
mayorSemiprimoMenor 50      ==  49
mayorSemiprimoMenor 49      ==  46
mayorSemiprimoMenor (10^6)  ==  999997

Leer más…

Ganadores de las elecciones

Los resultados de las votaciones a delegado en un grupo de clase se recogen mediante listas de asociación. Por ejemplo,

votos :: [(String,Int)]
votos = [("Ana Perez",10),("Juan Lopez",7), ("Julia Rus", 27),
         ("Pedro Val",1), ("Pedro Ruiz",27),("Berta Gomez",11)]

Definir la función

ganadores :: [(String,Int)] -> [String]

tal que (ganadores xs) es la lista de los estudiantes con mayor número de votos en xs. Por ejemplo,

ganadores votos == ["Julia Rus","Pedro Ruiz"]

Leer más…

Listas de igual longitud

Definir la función

mismaLongitud :: [[a]] -> Bool

tal que (mismaLongitud xss) se verifica si todas las listas de la lista de listas xss tienen la misma longitud. Por ejemplo,

mismaLongitud [[1,2],[6,4],[0,0],[7,4]] == True
mismaLongitud [[1,2],[6,4,5],[0,0]]     == False

Leer más…

Ternas con suma acotada

Definir la función

ternasAcotadas :: [Int] -> Int -> [(Int,Int,Int)]

tal que (ternasAcotadas xs n) es el conjunto de ternas de números naturales de xs cuya suma es menor que n. Por ejemplo,

ternasAcotadas [5,1,3,4,7] 12      ==  [(1,3,4),(1,3,5),(1,3,7),(1,4,5)]
ternasAcotadas [5,1,3,4,7] 11      ==  [(1,3,4),(1,3,5),(1,4,5)]
ternasAcotadas [5,1,3,4,7] 10      ==  [(1,3,4),(1,3,5)]
ternasAcotadas [5,1,3,4,7]  9      ==  [(1,3,4)]
ternasAcotadas [5,1,3,4,7]  8      ==  []
ternasAcotadas [1..10^6] 8         ==  [(1,2,3),(1,2,4)]
ternasAcotadas [10^6,10^6-1..1] 8  ==  [(1,2,3),(1,2,4)]

Leer más…

Subárboles monovalorados

Los árboles binarios con valores enteros se pueden representar mediante el tipo Arbol definido por

data Arbol = H Int
           | N Int Arbol Arbol
           deriving Show

Por ejemplo, el árbol

      7
     / \
    /   \
   /     \
  4       9
 / \     / \
1   3   5   6

se puede representar por

N 7 (N 4 (H 1) (H 3)) (N 9 (H 5) (H 6))

Un árbol es monovalorado si todos sus elementos son iguales. Por ejemplo, de los siguientes árboles sólo son monovalorados los dos primeros

  5          9           5          9
 / \        / \         / \        / \
5   5      9   9       5   6      9   7
              / \                    / \
             9   9                  9   9

Definir la función

monovalorados :: Arbol -> [Arbol]

tal que (monovalorados a) es la lista de los subárboles monovalorados de a. Por ejemplo,

λ> monovalorados (N 5 (H 5) (H 5))
[N 5 (H 5) (H 5),H 5,H 5]
λ> monovalorados (N 5 (H 5) (H 6))
[H 5,H 6]
λ> monovalorados (N 9 (H 9) (N 9 (H 9) (H 9)))
[N 9 (H 9) (N 9 (H 9) (H 9)),H 9,N 9 (H 9) (H 9),H 9,H 9]
λ> monovalorados (N 9 (H 9) (N 7 (H 9) (H 9)))
[H 9,H 9,H 9]
λ> monovalorados (N 9 (H 9) (N 9 (H 7) (H 9)))
[H 9,H 7,H 9]

Leer más…

Intersecciones parciales

Definir la función

interseccionParcial :: Eq a => Int -> [[a]] -> [a]

tal que (interseccionParcial n xss) es la lista de los elementos que pertenecen al menos a n conjuntos de xss. Por ejemplo,

interseccionParcial 1 [[3,4],[4,5,9],[5,4,7]]  == [3,4,5,9,7]
interseccionParcial 2 [[3,4],[4,5,9],[5,4,7]]  == [4,5]
interseccionParcial 3 [[3,4],[4,5,9],[5,4,7]]  == [4]
interseccionParcial 4 [[3,4],[4,5,9],[5,4,7]]  == []

Leer más…

Productos de N números consecutivos

La semana pasada se planteó en Twitter el siguiente problema

Se observa que

1x2x3x4 = 2x3x4 2x3x4x5 = 4x5x6

¿Existen ejemplos de otros productos de cuatro enteros consecutivos iguales a un producto de tres enteros consecutivos?

Definir la función

esProductoDeNconsecutivos :: Integer -> Integer -> Maybe Integer

tal que (esProductoDeNconsecutivos n x) es (Just m) si x es el producto de n enteros consecutivos a partir de m y es Nothing si x no es el producto de n enteros consecutivos. Por ejemplo,

esProductoDeNconsecutivos 3   6  == Just 1
esProductoDeNconsecutivos 4   6  == Nothing
esProductoDeNconsecutivos 4  24  == Just 1
esProductoDeNconsecutivos 3  24  == Just 2
esProductoDeNconsecutivos 3 120  == Just 4
esProductoDeNconsecutivos 4 120  == Just 2

Para ejemplos mayores,

λ> esProductoDeNconsecutivos 3 (product [10^20..2+10^20])
Just 100000000000000000000
λ> esProductoDeNconsecutivos2 4 (product [10^20..2+10^20])
Nothing
λ> esProductoDeNconsecutivos2 4 (product [10^20..3+10^20])
Just 100000000000000000000

Usando la función esProductoDeNconsecutivos resolver el problema.


Leer más…

Dígitos visibles y ocultos

Una cadena clave es una cadena que contiene dígitos visibles y ocultos. Los dígitos se ocultan mediante las primeras letras minúsculas: la 'a' oculta el '0', la 'b' el '1' y así sucesivamente hasta la 'j' que oculta el '9'. Los restantes símbolos de la cadena no tienen significado y se pueden ignorar.

Definir la función

numeroOculto :: String -> Maybe Integer

tal que (numeroOculto cs) es justo el número formado por los dígitos visibles u ocultos de la cadena clave cs, si cs tiene dígitos y Nothing en caso contrario. Por ejemplo,

numeroOculto "jihgfedcba"      ==  Just 9876543210
numeroOculto "JIHGFEDCBA"      ==  Nothing
numeroOculto "el 23 de Enero"  ==  Just 423344
numeroOculto "El 23 de Enero"  ==  Just 23344
numeroOculto "El 23 de enero"  ==  Just 233444
numeroOculto "Todo para nada"  ==  Just 300030

Leer más…

Números muy pares

Un entero positivo x es muy par si tanto x como x² sólo contienen cifras pares. Por ejemplo, 200 es muy par porque todas las cifras de 200 y 200² = 40000 son pares; pero 26 no lo es porque 26² = 767 tiene cifras impares.

Definir la función

siguienteMuyPar :: Integer -> Integer

tal que (siguienteMuyPar x) es menor número mayor que x que es muy par. Por ejemplo,

siguienteMuyPar 300           ==  668
siguienteMuyPar 668           ==  680
siguienteMuyPar 828268400000  ==  828268460602

Leer más…

Unión e intersección general de conjuntos.

Definir las funciones

unionGeneral        :: Eq a => [[a]] -> [a]
interseccionGeneral :: Eq a => [[a]] -> [a]

tales que + (unionGeneral xs) es la unión de los conjuntos de la lista de conjuntos xs (es decir, el conjunto de los elementos que pertenecen a alguno de los elementos de xs). Por ejemplo,

unionGeneral []                    ==  []
unionGeneral [[1]]                 ==  [1]
unionGeneral [[1],[1,2],[2,3]]     ==  [1,2,3]
unionGeneral ([[x] | x <- [1..9]]) ==  [1,2,3,4,5,6,7,8,9]
  • (interseccionGeneral xs) es la intersección de los conjuntos de la lista de conjuntos xs (es decir, el conjunto de los elementos que pertenecen a todos los elementos de xs). Por ejemplo,
interseccionGeneral [[1]]                      ==  [1]
interseccionGeneral [[2],[1,2],[2,3]]          ==  [2]
interseccionGeneral [[2,7,5],[1,5,2],[5,2,3]]  ==  [2,5]
interseccionGeneral ([[x] | x <- [1..9]])      ==  []

Leer más…

Ceros finales del factorial

Definir la función

cerosDelFactorial :: Integer -> Integer

tal que (cerosDelFactorial n) es el número de ceros en que termina el factorial de n. Por ejemplo,

cerosDelFactorial 24                           ==  4
cerosDelFactorial 25                           ==  6
length (show (cerosDelFactorial (1234^5678)))  ==  17552

Leer más…

Listas decrecientes

Definir la función

listasDecrecientesDesde :: Int -> [[Int]]

tal que (listasDecrecientesDesde n) es la lista de las sucesiones estrictamente decrecientes cuyo primer elemento es n. Por ejemplo,

λ> listasDecrecientesDesde 2
[[2],[2,1],[2,1,0],[2,0]]
λ> listasDecrecientesDesde 3
[[3],[3,2],[3,2,1],[3,2,1,0],[3,2,0],[3,1],[3,1,0],[3,0]]

Leer más…

Números autodescriptivos

Un número n es autodescriptivo cuando para cada posición k de n (empezando a contar las posiciones a partir de 0), el dígito en la posición k es igual al número de veces que ocurre k en n. Por ejemplo, 1210 es autodescriptivo porque tiene 1 dígito igual a "0", 2 dígitos iguales a "1", 1 dígito igual a "2" y ningún dígito igual a "3".

Definir la función

autodescriptivo :: Integer -> Bool

tal que (autodescriptivo n) se verifica si n es autodescriptivo. Por ejemplo,

λ> autodescriptivo 1210
True
λ> [x | x <- [1..100000], autodescriptivo x]
[1210,2020,21200]
λ> autodescriptivo 9210000001000
True

Leer más…

Primos gemelos próximos a múltiplos de 6

Un par de números primos (p,q) es un par de números primos gemelos si su distancia de 2; es decir, si q = p+2. Por ejemplo, (17,19) es una par de números primos gemelos.

Se dice que un par de números (x,y) está próximo a un múltiplo de 6 si es de la forma (6n-1,6n+1). Por ejemplo, (17,19) está cerca de un múltiplo de 6 porque (17,19) = (6·3-1,6·3+1).

Definir las funciones

primosGemelos :: Integer -> [(Integer,Integer)]
primosGemelosNoProximosAmultiplosDe6 :: Integer -> [(Integer,Integer)]

tales que

  • (primosGemelos n) es la lista de los primos gemelos menores que n. Por ejemplo,
primosGemelos 50  == [(3,5),(5,7),(11,13),(17,19),(29,31),(41,43)]
primosGemelos 43  == [(3,5),(5,7),(11,13),(17,19),(29,31)]
  • (primosGemelosNoProximosAmultiplosDe6 n) es la lista de los primos gemelos menores que n que no están próximos a un múltiplo de 6. Por ejemplo,
primosGemelosNoProximosAmultiplosDe6 50               == [(3,5)]
length (primosGemelosNoProximosAmultiplosDe6' (10^9)) == 1

Leer más…

Capicúas productos de dos números de dos dígitos

El número 9009 es capicúa y es producto de dos números de dos dígitos, pues 9009 = 91*99.

Definir la lista

capicuasP2N2D :: [Int]

cuyos elementos son los números capicúas que son producto de 2 números de dos dígitos. Por ejemplo,

take 5  capicuasP2N2D  ==  [121,242,252,272,323]
length  capicuasP2N2D  ==  74
drop 70 capicuasP2N2D  ==  [8008,8118,8448,9009]

Leer más…

Números muy divisibles por 3

Se dice que un número n es muy divisible por 3 si es divisible por 3 y sigue siendo divisible por 3 si vamos quitando dígitos por la derecha. Por ejemplo, 96060 es muy divisible por 3 porque 96060, 9606, 960, 96 y 9 son todos divisibles por 3.

Definir las funciones

muyDivPor3             :: Integer -> Bool
numeroMuyDivPor3Cifras :: Integer -> Integer

tales que

  • (muyDivPor3 n) se verifica si n es muy divisible por 3. Por ejemplo,
muyDivPor3 96060 == True
muyDivPor3 90616 == False
  • (numeroMuyDivPor3CifrasC k) es la cantidad de números de k cifras muy divisibles por 3. Por ejemplo,
numeroMuyDivPor3Cifras 5                    == 768
numeroMuyDivPor3Cifras 7                    == 12288
numeroMuyDivPor3Cifras (10^6) `rem` (10^6)  ==  332032

Leer más…

Números libres de cuadrados

Un número 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

tal que (libreDeCuadrados x) se verifica si x es libre de cuadrados. Por ejemplo,

libreDeCuadrados 70                    ==  True
libreDeCuadrados 40                    ==  False
libreDeCuadrados 510510                ==  True
libreDeCuadrados (((10^10)^10)^10)     ==  False

Leer más…

Aproximación del número pi

Una forma de aproximar el número π es usando la siguiente igualdad: \[ \frac{\pi}{2} = 1 + \frac{1}{3} + \frac{1 \cdot 2}{3 \cdot 5} + \frac{1 \cdot 2 \cdot 3}{3 \cdot 5 \cdot 7} + \frac{1 \cdot 2 \cdot 3 \cdot 4}{3 \cdot 5 \cdot 7 \cdot 9} + \cdots \] Es decir, la serie cuyo término general n-ésimo es el cociente entre el producto de los primeros n números y los primeros n números impares: \[s(n) = \frac{\prod_{i=1}^{n} i}{\prod_{i=1}^{n} (2i + 1)}\]

Definir la función

aproximaPi :: Double -> Double

tal que (aproximaPi n) es la aproximación del número π calculada con la serie anterior hasta el término n-ésimo. Por ejemplo,

aproximaPi 10   ==  3.141106021601377
aproximaPi 30   ==  3.1415926533011587
aproximaPi 50   ==  3.1415926535897922

Leer más…

Factoriales iguales a su número de dígitos

Se dice que un número n tiene un factorial especial si el número de dígitos de n! es igual a n. Por ejemplo, 22 tiene factorial especial porque 22! es 1124000727777607680000 que tiene 22 dígitos.

Definir la función

factorialesEspeciales :: [Integer]

tal que su valor es la lista de los números que tienen factoriales especiales. Por ejemplo,

take 2 factorialesEspeciales  ==  [1,22]

Nota: Si factorialesEspeciales es una lista finita, argumentar porqué no puede tener más elementos.


Leer más…

Próximos a múltiplos de 6

Se dice que un par de números (x,y) está próximo a un múltiplo de 6 si es de la forma (6*n-1,6*n+1). Por ejemplo, (17,19) está cerca de un múltiplo de 6 porque (17,19) = (6*3-1,6*3+1).

Definir la función

proximosAmultiplosDe6 :: (Integer,Integer) -> Bool

tal que (proximosAmultiplosDe6 (x,y)) se verifica si el par (x,y) está próximo a un múltiplo de 6. Por ejemplo,

proximosAmultiplosDe6 (17,19)                          ==  True
proximosAmultiplosDe6 (18,20)                          ==  False
proximosAmultiplosDe6 (5,19)                           ==  False
proximosAmultiplosDe6 (1,3)                            ==  False
proximosAmultiplosDe6 (74074073407403,74074073407405)  ==  True
proximosAmultiplosDe6 (86419752308637,86419752308639)  ==  False

Leer más…

Diferencia simétrica

La diferencia simétrica de dos conjuntos es el conjunto cuyos elementos son aquellos que pertenecen a alguno de los conjuntos iniciales, sin pertenecer a ambos a la vez. Por ejemplo, la diferencia simétrica de {2,5,3} y {4,2,3,7} es {5,4,7}.

Definir la función

diferenciaSimetrica :: Eq a => [a] -> [a] -> [a]

tal que (diferenciaSimetrica xs ys) es la diferencia simétrica de xs e ys. Por ejemplo,

diferenciaSimetrica [2,5,3] [4,2,3,7]    ==  [5,4,7]
diferenciaSimetrica [2,5,3] [5,2,3]      ==  []
diferenciaSimetrica [2,5,2] [4,2,3,7]    ==  [5,4,3,7]
diferenciaSimetrica [2,5,2] [4,2,4,7]    ==  [5,4,4,7]
diferenciaSimetrica [2,5,2,4] [4,2,4,7]  ==  [5,

Leer más…

Lista con repeticiones

Definir la función

tieneRepeticiones :: Eq a => [a] -> Bool

tal que (tieneRepeticiones xs) se verifica si xs tiene algún elemento repetido. Por ejemplo,

tieneRepeticiones [3,2,5,2,7]          ==  True
tieneRepeticiones [3,2,5,4,7]          ==  False
tieneRepeticiones (5:[1..2000000000])  ==  True
tieneRepeticiones [1..20000]           ==  False

Leer más…

Mayor resto

El resultado de dividir un número n por un divisor d es un cociente q y un resto r.

Definir la función

mayorResto :: Int -> Int -> (Int,[Int])

tal que (mayorResto n d) es el par (m,xs) tal que m es el mayor resto de dividir n entre x (con 1 ≤ x < d) y xs es la lista de números x menores que d tales que el resto de n entre x es m. Por ejemplo,

mayorResto 20 10  ==  (6,[7])
mayorResto 50 8   ==  (2,[3,4,6])

Nota: Se supone que d > 1.


Leer más…

Entero positivo con ciertas propiedades

El 6 de octubre, se propuso en el blog Gaussianos el siguiente problema

Demostrar que para todo entero positivo n, existe otro entero positivo que tiene las siguientes propiedades:

  1. Tiene exactamente n dígitos.
  2. Ninguno de sus dígitos es 0.
  3. Es divisible por la suma de sus dígitos.

Definir la función

especiales :: Integer -> [Integer]

tal que (especiales n) es la lista de los números enteros que cumplen las 3 propiedades anteriores para n. Por ejemplo,

take 3 (especiales 2)  ==  [12,18,21]
take 3 (especiales 3)  ==  [111,112,114]
head (especiales 30)   ==  111111111111111111111111111125
length (especiales 3)  ==  108
null (especiales 1000) ==  False

En el primer ejemplo, 12 es un número especial para 2 ya que tiene exactamente 2 dígitos, ninguno de sus dígitos es 0 y 12 es divisible por la suma de sus dígitos.


Leer más…

Centro de masas

El centro de masas de un sistema discreto es el punto geométrico que dinámicamente se comporta como si en él estuviera aplicada la resultante de las fuerzas externas al sistema.

Representamos un conjunto de n masas en el plano mediante una lista de n pares de la forma ((a(i),b(i)),m(i)) donde (a(i),b(i)) es la posición y m(i) la masa puntual. Las coordenadas del centro de masas (a,b) se calculan por

a = (a(1)·m(1) + a(2)·m(2) + ... + a(n)·m(n)) / (m(1) + m(2) +...+ m(n))
b = (b(1)·m(1) + b(2)·m(2) + ... + b(n)·m(n)) / (m(1) + m(2) +...+ m(n))

Definir la función

centrodeMasas :: [((Float,Float),Float)] -> (Float,Float)

tal que (centrodeMasas xs) es las coordenadas del centro de masas del sistema discreto xs. Por ejemplo:

centrodeMasas [((-1,3),2),((0,0),5),((1,3),3)] == (0.1,1.5)

Leer más…

Refinamiento de listas

Definir la función

refinada :: [Float] -> [Float]

tal que (refinada xs) es la lista obtenida intercalando entre cada dos elementos consecutivos de xs su media aritmética. Por ejemplo,

refinada [2,7,1,8]  ==  [2.0,4.5,7.0,4.0,1.0,4.5,8.0]
refinada [2]        ==  [2.0]
refinada []         ==  []

Leer más…

Pandigitales tridivibles

El número 4106357289 tiene la siguientes dos propiedades:

  • es pandigital, porque tiene todos los dígitos del 0 al 9 exactamente una vez y
  • es tridivisible, porque los sucesivos subnúmeros de tres dígitos (a partir del segundo) son divisibles por los sucesivos números primos; es decir, representado por d(i) el i-ésimo dígito, se tiene
d(2)d(3)d(4)  = 106 es divisible por 2
d(3)d(4)d(5)  = 063 es divisible por 3
d(4)d(5)d(6)  = 635 es divisible por 5
d(5)d(6)d(7)  = 357 es divisible por 7
d(6)d(7)d(8)  = 572 es divisible por 11
d(7)d(8)d(9)  = 728 es divisible por 13
d(8)d(9)d(10) = 289 es divisible por 17

Definir la constante

pandigitalesTridivisibles :: [Integer]

cuyos elementos son los números pandigitales tridivisibles. Por ejemplo,

head pandigitalesTridivisibles  ==  4106357289
sum pandigitalesTridivisibles   ==  16695334890

Leer más…

Pandigitales primos

Un número con n dígitos es pandigital si contiene todos los dígitos del 1 a n exactamente una vez. Por ejemplo, 2143 es un pandigital con 4 dígitos y, además, es primo.

Definir la constante

pandigitalesPrimos :: [Int]

tal que sus elementos son los números pandigitales, ordenados de mayor a menor. Por ejemplo,

take 3 pandigitalesPrimos       ==  [7652413,7642513,7641253]
2143 `elem` pandigitalesPrimos  ==  True
length pandigitalesPrimos       ==  538

Leer más…

Codificación de Fibonacci

La codificación de Fibonacci de un número n es una cadena d = d(0)d(1)...d(k-1)d(k) de ceros y unos tal que

n = d(0)·F(2) + d(1)·F(3) +...+ d(k-1)·F(k+1)
d(k-1) = d(k) = 1

donde F(i) es el i-ésimo término de la sucesión de Fibonacci.

0,1,1,2,3,5,8,13,21,34,...

Por ejemplo. La codificación de Fibonacci de 4 es "1011" ya que los dos últimos elementos son iguales a 1 y

1·F(2) + 0·F(3) + 1·F(4) = 1·1 + 0·2 + 1·3 = 4

La codificación de Fibonacci de los primeros números se muestra en la siguiente tabla

 1  = 1     = F(2)           ≡       11
 2  = 2     = F(3)           ≡      011
 3  = 3     = F(4)           ≡     0011
 4  = 1+3   = F(2)+F(4)      ≡     1011
 5  = 5     = F(5)           ≡    00011
 6  = 1+5   = F(2)+F(5)      ≡    10011
 7  = 2+5   = F(3)+F(5)      ≡    01011
 8  = 8     = F(6)           ≡   000011
 9  = 1+8   = F(2)+F(6)      ≡   100011
10  = 2+8   = F(3)+F(6)      ≡   010011
11  = 3+8   = F(4)+F(6)      ≡   001011
12  = 1+3+8 = F(2)+F(4)+F(6) ≡   101011
13  = 13    = F(7)           ≡  0000011
14  = 1+13  = F(2)+F(7)      ≡  1000011

Definir la función

codigoFib :: Integer -> String

tal que (codigoFib n) es la codificación de Fibonacci del número n. Por ejemplo,

λ> codigoFib 65
"0100100011"
λ> [codigoFib n | n <- [1..7]]
["11","011","0011","1011","00011","10011","01011"]

Leer más…

Partición por longitudes

Definir la función

particion :: [a] -> [Int] -> [[a]]

tal que (particion xs ns) es la partición de xs donde la longitud de cada parte está determinada por los elementos de ns. Por ejemplo,

particion [1..10] [2,5,0,3]  ==  [[1,2],[3,4,5,6,7],[],[8,9,10]]
particion [1..10] [1,4,2,3]  ==  [[1],[2,3,4,5],[6,7],[8,9,10]]

Leer más…

Máximos de una lista

Definir la función

maximos :: Ord a => [a] -> [a]

tal que (maximos xs) es la lista de los elementos de xs que son mayores que todos sus anteriores. Por ejemplo,

maximos [1,-3,5,2,3,4,7,6,7]                         ==  [1,5,7]
maximos "bafcdegag"                                  ==  "bfg"
maximos (concat (replicate (10^6) "adxbcde")++"yz")  ==  "adxyz"
length (maximos [1..10^6])                           ==  1000000

Leer más…

La sucesión del reloj astronómico de Praga

La cadena infinita "1234321234321234321...", formada por la repetición de los dígitos 123432, tiene una propiedad (en la que se basa el funcionamiento del reloj astronómico de Praga: la cadena se puede partir en una sucesión de números, de forma que la suma de los dígitos de dichos números es la serie de los números naturales, como se observa a continuación:

1, 2, 3, 4, 32, 123, 43, 2123, 432, 1234, 32123, ...
1, 2, 3, 4,  5,   6,  7,    8,   9,   10,    11, ...

Definir la lista

reloj :: [Integer]

cuyos elementos son los términos de la sucesión anterior. Por ejemplo,

λ> take 11 reloj
[1,2,3,4,32,123,43,2123,432,1234,32123]

Nota: La relación entre la sucesión y el funcionamiento del reloj se puede ver en The Mathematics Behind Prague's Horloge Introduction.


Leer más…

Menor n tal que el primo n-ésimo cumple una propiedad

Sea p(n) el n-ésimo primo y sea r el resto de dividir (p(n)-1)^n + (p(n)+1)^n por p(n)^2. Por ejemplo,

si n = 3, entonces p(3) =  5 y r = ( 4^3 +  6^3) mod  (5^2) =   5
si n = 7, entonces p(7) = 17 y r = (16^7 + 18^7) mod (17^2) = 238

Definir la función

menorPR :: Integer -> Integer

tal que (menorPR x) es el menor n tal que el resto de dividir (p(n)-1)^n + (p(n)+1)^n por p(n)^2 es mayor que x. Por ejemplo,

menorPR 100     == 5
menorPR 345     == 9
menorPR 1000    == 13
menorPR (10^9)  == 7037
menorPR (10^10) == 21035
menorPR (10^12) == 191041

Leer más…

Polinomio cromático de un grafo

El polinomio cromático de un grafo calcula el número de maneras en las cuales puede ser coloreado el grafo usando un número de colores dado, de forma que dos vértices adyacentes no tengan el mismo color.

En el caso del grafo completo de n vértices, su polinomio cromático es

P(n,x) = x(x-1)(x-2) ... (x-(n-1))

Por ejemplo,

P(3,x) = x(x-1)(x-2)      = x^3 - 3·x^2 + 2·x
P(4,x) = x(x-1)(x-2)(x-3) = x^4 - 6·x^3 + 11·x^2 - 6·x

Lo que significa que P(4)(x) es el número de formas de colorear el grafo completo de 4 vértices con x colores. Por tanto,

P(4,2) =  0 (no se puede colorear con 2 colores)
P(4,4) = 24 (hay 24 formas de colorearlo con 4 colores)

Definir la función

polGC:: Int -> Polinomio Int

tal que (polGC n) es el polinomio cromático del grafo completo de n vértices. Por ejemplo,

polGC 4  ==  x^4 + -6*x^3 + 11*x^2 + -6*x
polGC 5  ==  x^5 + -10*x^4 + 35*x^3 + -50*x^2 + 24*x

Comprobar con QuickCheck que si el número de colores (x) coincide con el número de vértices del grafo (n), el número de maneras de colorear el grafo es n!.

Nota 1. Al hacer la comprobación limitar el tamaño de las pruebas como se indica a continuación

λ> quickCheckWith (stdArgs {maxSize=7}) prop_polGC
+++ OK, passed 100 tests.

Nota 2: Este ejercicio debe realizarse usando únicamente las funciones de la librería de polinomios (I1M.PolOperaciones) que aquí.


Leer más…

Suma de posteriores

Definir la función

sumaPosteriores :: [Int] -> [Int]

tal que (sumaPosteriores xs) es la lista obtenida sustituyendo cada elemento de xs por la suma de los elementos posteriores. Por ejemplo,

sumaPosteriores [1..8]        == [35,33,30,26,21,15,8,0]
sumaPosteriores [1,-3,2,5,-8] == [-4,-1,-3,-8,0]

Comprobar con QuickCheck que el último elemento de la lista (sumaPosteriores xs) siempre es 0.


Leer más…

Algoritmo de bajada para resolver un sistema triangular inferior

Un sistema de ecuaciones lineales Ax = b es triangular inferior si todos los elementos de la matriz A que están por encima de la diagonal principal son nulos; es decir, es de la forma

a(1,1)·x(1)                                               = b(1)
a(2,1)·x(1) + a(2,2)·x(2)                                 = b(2)
a(3,1)·x(1) + a(3,2)·x(2) + a(3,3)·x(3)                   = b(3)
...
a(n,1)·x(1) + a(n,2)·x(2) + a(n,3)·x(3) +...+ a(x,x)·x(n) = b(n)

El sistema es compatible si, y sólo si, el producto de los elementos de la diagonal principal es distinto de cero. En este caso, la solución se puede calcular mediante el algoritmo de bajada:

x(1) = b(1) / a(1,1)
x(2) = (b(2) - a(2,1)·x(1)) / a(2,2)
x(3) = (b(3) - a(3,1)·x(1) - a(3,2)·x(2)) / a(3,3)
...
x(n) = (b(n) - a(n,1)·x(1) - a(n,2)·x(2) -...- a(n,n-1)·x(n-1)) / a(n,n)

Definir la función

bajada :: Matrix Double -> Matrix Double -> Matrix Double

tal que (bajada a b) es la solución, mediante el algoritmo de bajada, del sistema compatible triangular superior ax = b. Por ejemplo,

λ> let a = fromLists [[2,0,0],[3,1,0],[4,2,5.0]]
λ> let b = fromLists [[3],[6.5],[10]]
λ> bajada a b
( 1.5 )
( 2.0 )
( 0.0 )

Es decir, la solución del sistema

2x            = 3
3x + y        = 6.5
4x + 2y + 5 z = 10

es x=1.5, y=2 y z=0.


Leer más…

Mayor producto de n números adyacentes en una matriz

Definir la función

mayorProductoAdyacentes :: (Num a, Ord a) => Int -> Matriz a -> [[a]]

tal que (mayorProductoAdyacentes n p) es la lista de los segmentos formados por n elementos adyacentes en la misma fila, columna o diagonal de la matriz p cuyo productos son máximo. Por ejemplo,

λ> mayorProductoAdyacentes 3 (listArray ((1,1),(3,4)) [1..12])
[[10,11,12]]
λ> mayorProductoAdyacentes 3 (listArray ((1,1),(3,4)) [1,3,4,5, 0,7,2,1, 3,9,2,1])
[[3,7,9]]
λ> mayorProductoAdyacentes 2 (listArray ((1,1),(2,3)) [1,3,4, 0,3,2])
[[3,4],[4,3]]
λ> mayorProductoAdyacentes 2 (listArray ((1,1),(2,3)) [1,2,1, 3,0,3])
[[2,3],[2,3]]
λ> mayorProductoAdyacentes 2 (listArray ((1,1),(2,3)) [1,2,1, 3,4,3])
[[3,4],[4,3]]
λ> mayorProductoAdyacentes 2 (listArray ((1,1),(2,3)) [1,5,1, 3,4,3])
[[5,4]]
λ> mayorProductoAdyacentes 3 (listArray ((1,1),(3,4)) [1,3,4,5, 0,7,2,1, 3,9,2,1])
[[3,7,9]]

Leer más…

Método de bisección para encontrar raíces de funciones

El método de bisección para calcular un cero de una función en el intervalo [a,b] se basa en el teorema de Bolzano:

Si f(x) es una función continua en el intervalo [a, b], y si, además, en los extremos del intervalo la función f(x) toma valores de signo opuesto (f(a) * f(b) < 0), entonces existe al menos un valor c en (a, b) para el que f(c) = 0".

El método para calcular un cero de la función f en el intervalo [a,b] con un error menor que e consiste en tomar el punto medio del intervalo c = (a+b)/2 y considerar los siguientes casos:

  • Si |f(c)| < e, hemos encontrado una aproximación del punto que anula f en el intervalo con un error aceptable.
  • Si f(c) tiene signo distinto de f(a), repetir el proceso en el intervalo [a,c].
  • Si no, repetir el proceso en el intervalo [c,b].

Definir la función

biseccion :: (Double -> Double) -> Double -> Double -> Double -> Double

tal que (biseccion f a b e) es una aproximación del punto del intervalo [a,b] en el que se anula la función f, con un error menor que e, calculada mediante el método de la bisección. Por ejemplo,

biseccion (\x -> x^2 - 3) 0 5 0.01             ==  1.7333984375
biseccion (\x -> x^3 - x - 2) 0 4 0.01         ==  1.521484375
biseccion cos 0 2 0.01                         ==  1.5625
biseccion (\x -> log (50-x) - 4) (-10) 3 0.01  ==  -5.125

Leer más…

Números para los que mcm de 1,2,...n-1 coincide con el de 1,2,...,n

Un número n es especial si mcm(1,2,...,n-1) = mcm(1,2,...,n). Por ejemplo, el 6 es especial ya que

mcm(1,2,3,4,5) = 60 = mcm(1,2,3,4,5,6)

Definir la sucesión

especiales :: [Integer]

cuyos términos son los números especiales. Por ejemplo,

take 10 especiales     ==  [1,6,10,12,14,15,18,20,21,22]
especiales !! 50       ==  84
especiales !! 500      ==  638
especiales !! 5000     ==  5806
especiales !! 50000    ==  55746

Leer más…

Cálculo aproximado de integrales definidas

La integral definida de una función f entre los límites a y b puede calcularse mediante la regla del rectángulo usando la fórmula \[ h \cdot \left( f\left(a + \frac{h}{2}\right) + f\left(a + h + \frac{h}{2}\right) + f\left(a + 2h + \frac{h}{2}\right) + \dots + f\left(a + nh + \frac{h}{2}\right) \right) \] con \[ a + n h + \frac{h}{2} \leq b < a + (n+1) h + \frac{h}{2} \] y usando valores pequeños para \(h\).

Definir la función

integral :: (Fractional a, Ord a) => a -> a -> (a -> a) -> a -> a

tal que (integral a b f h) es el valor de dicha expresión. Por ejemplo, el cálculo de la integral de f(x) = x^3 entre 0 y 1, con paso 0.01, es

integral 0 1 (^3) 0.01  ==  0.24998750000000042

Otros ejemplos son

integral 0 1 (^4) 0.01                   ==  0.19998333362500048
integral 0 1 (\x -> 3*x^2 + 4*x^3) 0.01  ==  1.9999250000000026
log 2 - integral 1 2 (\x -> 1/x) 0.01         ==  3.124931644782336e-6
pi - 4 * integral 0 1 (\x -> 1/(x^2+1)) 0.01  ==  -8.333333331389525e-6

Leer más…

Menor número con una cantidad de divisores dada

El menor número con 2¹ divisores es el 2, ya que tiene 2 divisores (el 1 y el 2) y el anterior al 2 (el 1) sólo tiene 1 divisor (el 1).

El menor número con 2² divisores es el 6, ya que tiene 4 divisores (el 1, 2, 3 y 6) y sus anteriores (el 1, 2, 3, 4 y 5) tienen menos de 4 divisores (tienen 1, 1, 1, 3 y 1, respectivamente).

El menor número con 2³ divisores es el 24, ya que tiene 8 divisores (el 1, 2, 3, 4, 6, 8, 12 y 24) y sus anteriores (del 1 al 23) tienen menos de 8 divisores.

El menor número con 2⁴ divisores es el 120, ya que tiene 16 divisores (el 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60 y 120) y sus anteriores (del 1 al 119) tienen menos de 16 divisores.

El menor número, módulo 100, con 2⁴ divisores es el 20, ya que el menor número con 16 divisores es el 120 y 120 módulo 100 es 20.

Definir la función

menor :: Integer -> Integer -> Integer

tal que (menor n m) es el menor número, módulo m, con 2^n divisores; es decir, es el resto de dividir entre m el menor número con 2^n divisores. Por ejemplo,

menor 4 1000                    ==  120
menor 4 100                     ==  20
[menor n (10^9) | n <- [1..8]]  ==  [2,6,24,120,840,7560,83160,1081080]
menor 500500 500500506          ==  8728302

Leer más…