Herramientas de usuario

Herramientas del sitio


introalg:taller09_soluciones

¡Esta es una revisión vieja del documento!


Soluciones a ejercicios

ejercicios de prolog, 30/03/09

familia

%%%%%%%%%%%%
%% HECHOS %%
%%%%%%%%%%%%

mujer(pepa).
mujer(lucía).
mujer(blanca).
mujer(rosa).
mujer(alba).
mujer(inés).
mujer(irene).
hombre(armando).
hombre(julián).
hombre(esteban).
hombre(mario).
hombre(alejandro).
hombre(martín).
hombre(matías).
progenitor(pepa,lucía).
progenitor(pepa,blanca).
progenitor(pepa,mario).
progenitor(lucía,rosa).
progenitor(lucía,alba).
progenitor(blanca,inés).
progenitor(blanca,martín).
progenitor(irene,matías).
progenitor(armando,lucía).
progenitor(armando,blanca).
progenitor(armando,mario).
progenitor(julián,rosa).
progenitor(julián,alba).
progenitor(alejandro,inés).
progenitor(alejandro,martín).
progenitor(mario,matías).

%%%%%%%%%%%%
%% REGLAS %%
%%%%%%%%%%%%

padre(X,Y) :- hombre(X), progenitor(X,Y).
madre(X,Y) :- mujer(X), progenitor(X,Y).
hijo(X,Y) :- hombre(X), progenitor(Y,X).
hija(X,Y) :- mujer(X), progenitor(Y,X).
abuelo(X,Y) :- hombre(X), progenitor(X,Z), progenitor(Z,Y).
abuela(X,Y) :- mujer(X), progenitor(X,Z), progenitor(Z,Y).

hermano(X,Y) :- hombre(X), progenitor(Z,X), progenitor(Z,Y), not(X=Y).
hermana(X,Y) :- mujer(X), progenitor(Z,X), progenitor(Z,Y), not(X=Y).
tío(X,Y) :- hermano(X,Z), progenitor(Z,Y).
tía(X,Y) :- hermana(X,Z), progenitor(Z,Y).
primo(X,Y) :- hijo(X,Z), progenitor(W,Y), ( hermano(Z,W) ; hermana(Z,W) ).
prima(X,Y) :- hija(X,Z), progenitor(W,Y), ( hermano(Z,W) ; hermana(Z,W) ).
hijoúnico(X) :- not(hermano(_,X) ; hermana(_,X)). % vamos a ver más sobre este problema en la clase

Otra opción para hijo único que funciona mejor, más acorde a nuestras intuiciones sobre el concepto:

hijoúnico(X) :- ( hombre(X) ; mujer(X) ) , ( not(hermano(_,X) ; hermana(_,X)) ).

Esta opción funciona mejor porque el árbol de búsqueda de resultados que se arma y sobre el cual el intérprete hace backtracking es considerablemente distinto.

ejercicios de prolog, 6/04/09

extensión de familia

Incorporamos cuñados, suegras y demás familias políticas. Para ello nos resultará muy útil definir el predicado “pareja”, y podremos escribir el resto de relaciones en función de ella.

pareja(X,Y) :- progenitor(X,Z), progenitor(Y,Z).

cuñado(X,Y) :- hermano(X,Z), pareja(Z,Y).
cuñada(X,Y) :- hermana(X,Z), pareja(Z,Y).
suegra(X,Y) :- madre(X,Z), pareja(Y,Z).
suegro(X,Y) :- padre(X,Z), pareja(Y,Z).

Fíjense que no hay que explicitar el sexo del cuñado, suegra, etc. porque ya está implícito en los predicados “hermano” y “madre”, respectivamente.

Para incorporar la regla “hermano mayor”, la única posibilidad es declarar hechos nuevos, en concreto, hechos que nos permitan saber si alguien es mayor o menor que otra persona. Eso se puede hacer más o menos ad hoc: lo más ad hoc que se me ocurre es declarar el hecho mayorQue entre los pares de hermanos, lo menos ad hoc, declarar la edad de cada persona e inferir de ese dato la relación mayorQue, de la siguiente manera:

%%% declaramos hechos sobre la edad de algunos miembros de la familia %%%
edad(lucía,28).
edad(blanca,26).
edad(mario,24).

mayor(X,Y) :- edad(X,EX), edad(Y,EY), EX>EY.

hermanoMayor(X,Y) :- hermano(X,Y), mayor(X,Y).
hermanoMenor(X,Y) :- hermano(X,Y), mayor(Y,X).
hermanaMayor(X,Y) :- hermana(X,Y), mayor(X,Y).
hermanaMenor(X,Y) :- hermana(X,Y), mayor(Y,X).

ejercicios de haskell, 13/04/09

* ordena :: (Int,Int) → (Int,Int) que, dados dos enteros, los ordena de menor a mayor.

ordena :: (Int,Int) -> (Int,Int)
ordena (x,y) |   x < y    = (x,y)
             |   x > y    = (y,x)
             |   x == y   = (x,y)
ordena' :: (Int,Int) -> (Int,Int)
ordena' (x,y) |   x <= y    = (x,y)
              |   x >  y    = (y,x)
  • ambospositivos :: Int → Int → Bool, que dados dos enteros devuelve True si los dos son positivos.
ambospositivos :: Int -> Int -> Bool
ambospositivos x y | x >= 0 && y >= 0 = True
                   | x >= 0 || y < 0  = False
ambospositivos'' :: Int -> Int -> Bool
ambospositivos'' x y = x >= 0 && y >= 0 
  • edad :: (Int, Int, Int) → (Int, Int, Int) → Int que dadas dos fechas indica los años transcurridos entre ellas. Por ejemplo edad (20,10,1968) (30,4,1987) = 18.
edad :: (Int, Int, Int) -> (Int, Int, Int) -> Int
edad (diaN,mesN,anioN) (diaA,mesA,anioA) | (mesN < mesA) || (mesN == mesA && diaN < diaA) = (anioA - anioN) - 1
                                         | otherwise                                      = anioA - anioN
  • cabeza :: [a] –> a, que devuelve el primer elemento de una lista.
cabeza :: [a] -> a
cabeza (x:_) = x
cabeza []     = error "la lista es vacía y por lo tanto no tiene cabeza!"
  • cola :: [a] –> [a], que devuelve toda la lista menos el primer elemento.
cola :: [a] -> [a]
cola (_:xs) = xs
cola []     = [] 
  • Definición del área de un prisma.
area :: Int -> Int -> Int -> Int
area alto ancho fondo = 2*frente + 2*lado + 2*tapa
  where
    frente = alto * ancho
    lado   = alto * fondo 
    tapa   = ancho * fondo
  • esVaciaOPrimer0 :: [Int] → Bool que dada una lista decida si es vacía o bien su primer elemento es 0.
esVaciaOPrimer0 :: [Int] -> Bool
esVaciaOPrimer0 []                = True
esVaciaOPrimer0 (x:_) | x == 0    = True
                      | otherwise = False
esVaciaOPrimer0' :: [Int] -> Bool
esVaciaOPrimer0' []    = True
esVaciaOPrimer0' (x:_) = x == 0
  • segundoEsSegundo :: (Int,Int) → [Int] → Bool que dada una tupla de enteros y una lista de enteros comprueba si el segundo elemento de la tupla es igual al segundo elemento de la lista.
segundoEsSegundo :: (Int,Int) -> [Int] -> Bool
segundoEsSegundo (_,x) (_:y:_) = x == y
  • recortaDia :: [Char] → [Char] que dada una lista de caracteres, comprueba si las letras de la lista forman el nombre de un día de la semana, si es así, si el día no es del fin de semana, devuelven la primera letra solamente, en cambio, si el día es de fin de semana, devuelven el nombre del día completo. Ayuda: fíjense que el resultado siempre debe ser una lista de caracteres
recortaDia :: [Char] -> [Char]
recortaDia x:xs | (x:xs) == "lunes" || (x:xs) == "martes" || (x:xs) == "miercoles" || (x:xs) == "jueves" || (x:xs) == "viernes" = [x]
                | (x:xs) == "sabado" || (x:xs) == "domingo" = (x:xs)
                | otherwise = error "el string de entrada no es un dia de la semana o tiene mayusculas o acentos"

ejercicios para seguir pensando y analizando problemas

  • ¿Cómo sería un programa para recomendar amigos en una red social tipo facebook?

Algunos de sus compañeros propusieron una solución a este problema, aplicando recursividad. Después del primer parcialito, cuando ya tengan bien asumida la recursividad, vamos a poner en común todo lo que han venido pensando y analizando para ver diferentes formas de encarar este problema.

  • ¿Cómo podemos hacer un programa no muy largo que, dado un animal, nos diga si es ovíparo o vivíparo, si vive en la tierra, en el agua o en el aire, si come carne o vegetales, etc.? Traten de usar generalizaciones del tipo si es mamífero, entonces…. En esta aproximación, cómo tratarían excepciones como “delfín” o “guppi”?
  • Tenemos una lista de las conexiones por tren entre pares de ciudades, por ejemplo conectadas(Tarragona,Barcelona). . ¿Cómo sería un programa que nos ayudara a saber si podemos llegar de una ciudad a otra, es decir, si existe una lista de conexiones que nos lleve de una ciudad a otra, o bien eso es imposible? Primero, traten de hacer un programa que nos diga si podemos llegar de una ciudad a otra directamente o bien en dos o en tres pasos…

Para resolver este problema también vamos a hacer un uso intensivo de recursividad.

introalg/taller09_soluciones.1240318803.txt.gz · Última modificación: 2018/08/10 03:03 (editor externo)