Buenas, gracias por la data, adjunto mi resolucion por si alguno quiere comparar para el final del sabado:
Parte logico:
1) El problema es que solo esta validando que haya cumplido UNA SOLA correlativa, en vez de todas las posibles.
En el caso de una materia tenga 2 correlativas y al menos se haya cumplido una, este consulta devuelve TRUE, aun faltando 1 correlativa.
2) puedeAnotarseAFinal/3 es inversible para Alumno y para Materia, ya que utiliza el predicado aproboCursada/3 que es inversible para todos sus parámetros, por lo que liga las variables, pero para la Fecha de inscripción no hay ninguna forma de ligarlo.
Para solucionarlo agregaria un hecho:
fechaFinal(18/11)
fechaFinal(19/11)
en el caso de que se pueda rendir cualquier materia en una fecha de final.
Otra solución posible seria:
fechaFinal(18/11, Materia) en el cual se relaciona una materia con una fecha de final confirmada.
3)
puedeAnotarse(Alumno,Materia,Fecha):-
fechaFinal(Fecha,Materia),
aproboCursada(Alumno,Materia,_),
not(aproboFinal(Alumno,Materia,_)),
cumpleCorrelativas(Alumno, Materia,Fecha).
cumpleCorrelativas(Alumno,Materia,Fecha):-
aproboCursada(Alumno,Materia,FechaFirma),
añoLectivosTranscurridos(FechaFirma,Fecha,0).
cumpleCorrelativas(Alumno,Materia,_):-
forall(correlativa(Correlativa,Materia), aproboFinal(Alumno,Correlativa,_)).
Parte Funcional:
1)
data Persona = Persona{
edad :: Int,
nacionalidad :: String,
vestimenta :: [String]
}
type Requisito = Persona -> Bool
type Local = [Requisito]
edadPersona :: Persona -> Int
edadPersona (Persona e _ _) = e
nacionalidadPersona :: Persona -> String
nacionalidadPersona (Persona _ nac _) = nac
vestimentaPersona :: Persona -> [String]
vestimentaPersona (Persona _ _ ves) = ves
nacionalidadNoAceptada :: String -> Requisito
nacionalidadNoAceptada nac = ((/= nac).nacionalidadPersona)
edadMinima :: Int -> Requisito
edadMinima edadMinimo = ((>= edadMinimo).edadPersona)
prendaProhibida :: String -> Requisito
prendaProhibida prenda = (not.(elem prenda).vestimentaPersona)
2)
kravi = [(nacionalidadNoAceptada "Kenia"),(edadMinima 18), (prendaProhibida "Musculosa")]
3)
puedeEntrar :: Local -> Persona -> Bool
puedeEntrar requisitos persona = (foldl1 (&&) . map ($ persona)) requisitos
patovica :: Local -> [Persona] -> [Persona]
patovica requisitos = filter (puedeEntrar requisitos)
4) Composición: Para aprovechar las ventajas del paradigma en los requisitos y favorecer el uso de la aplicación parcial.
Se puede observar en nacionalidadNoAceptada, edadMinima, por ejemplo.
Aplicación parcial: Para poder armar una lista de Requisitos, sin importar el requisito que sea, se debe usar aplicación parcial para poder introducir el parámetro.
De esta forma, se pueden crear requisitos indistintamente de si precisan una edad, una ropa o una nacionalidad.
Orden superior: en PrendaProhibida se utiliza "NOT", una función de orden superior que toma como parámetro otra función.
Otro ejemplo es cuando se habla de un local, ya que el mismo es una lista de Requisitos y, a su vez, requisito es una función del tipo "Persona -> Bool"
Parte objetos:
1)a) Podría no ser una clase, sino una interfaz, ya que lo que importa de "Vehículo" es que implemente los métodos "Tarifa" y "CobrarleA"
1)b) Verdadero, ya que se envia un mensaje a todos los vehiculos y cada uno lo entiende y da una respuesta segun su propia definicion.
1)c) Verdadero, el metodo pagarPeaje() deberia ser delegado en una interfaz "metodoDePago" que implemente el metodo "pagarPeaje()" y alli, crear los distintos medios de pago con sus implemenmtaciones (Telepeaje, efectivo y sube)
1)d) Falso, debido a lo mencionado en el 1)c) va a necesitar crearse de cero, utilizando una clase distinta solo para poder utilizar otro medio de pago.
1)e) Falso, si no hay un manejo de excepciones que valide a la hora de hacer el descuento del total de peajesDisponibles, puede quedar en negativo, permitiendole pasar sin tener ningun peaje disponible al momento del cobro.
2)
public class Autopista{
private Vehiculo[] vehiculos;
private int saldo= 0;
public void cobrarPeaje(){
vehiculos.forEach{ v => v.pagarPeaje(self)};
}
public void cobrarPeaje(Int dinero){
saldo += dinero;
}
}
public abstract class Vehiculo{
private MetodoDePago metodoDePago;
public int tarifa(){
return precioBase() + metodoDePago.comision();
}
void pagarPeaje(Autopista autopista){
autopista.cobrarPeaje(self.tarifa());
metodoDePago.pagarPeaje(self.tarifa());
}
public int precioBase();
}
public class Camion{
private int cantidadEjes;
public int precioBase(){
return 20 * cantidadEjes;
}
}
public class Auto{
public int precioBase(){
return 60;
}
}
public interface MetodoDePago{
void pagarPeaje(int tarifa);
}
public class Efectivo implements MetodoDePago{
public void pagarPeaje(int tarifa){
}
}
public class Sube implements MetodoDePago{
private float saldoSube;
public void pagarPeaje(int tarifa){
saldoSube -= tarifa*1.1;
}
}
public class Pass implements MetodoDePago{
private int peajesDisponibles;
public void pagarPeaje(int tarifa){
if(peajesDisponibles == 0){
throw new noHayMasPeajesException("No quedan mas peajes disponibles para pagar");
}
peajesDisponibles -= 1;
}
}
3) Lo único que debería contemplarse para agregar mas vehículos es que hereden de la clase abstracta e implementen el método precioBase() así como que posean un método de pago valido.
Saludos!