Próxima revisión | Revisión previa |
introalg:taller09_10 [2009/06/09 19:37] – creado laura | introalg:taller09_10 [2018/08/10 03:03] (actual) – editor externo 127.0.0.1 |
---|
* Usando ''map'', ''filter'' y ''foldr'', definir la función ''porCientoMayorQue :: Int -> Int -> [Int] -> Int'', que dado un número ''n'', otro número ''m'' y una lista de enteros, devuelve la suma de todos los porcentajes mayores que ''n''. **Ayuda:** definir una función auxiliar ''PorCiento :: Int -> Int -> Int'' que use la función ''div'' que devuelve la división entera de dos enteros. | * Usando ''map'', ''filter'' y ''foldr'', definir la función ''porCientoMayorQue :: Int -> Int -> [Int] -> Int'', que dado un número ''n'', otro número ''m'' y una lista de enteros, devuelve la suma de todos los porcentajes mayores que ''n''. **Ayuda:** definir una función auxiliar ''PorCiento :: Int -> Int -> Int'' que use la función ''div'' que devuelve la división entera de dos enteros. |
| |
Ejemplo: ''porCientoMayorQue 10 50 [22,4,30,10] = 26.'' | Ejemplo: porCientoMayorQue 10 50 [22,4,30,10] = 26. |
| |
== solución == | == solución == |
Para plantear el problema, deben definir dos funciones (o predicados) con la siguiente semántica: | Para plantear el problema, deben definir dos funciones (o predicados) con la siguiente semántica: |
<code> | <code> |
''puedeTomarPrestado -> usuario -> libro -> Bool'' | puedeTomarPrestado -> usuario -> libro -> Bool |
''puedeReservar -> usuario -> libro -> Bool'' | puedeReservar -> usuario -> libro -> Bool |
</code> | </code> |
| |
%% después de los hechos, definimos las reglas | %% después de los hechos, definimos las reglas |
puedeTomarPrestado(Usuario,Libro) :- | puedeTomarPrestado(Usuario,Libro) :- |
usuario(Usuario,Prestados,Reservados), | usuario(Usuario,Prestados,_), |
libro(Libro,nopres,nores), | libro(Libro,nopres,nores), |
Prestados < 6. | Prestados < 6. |
| |
puedeReservar(Usuario) :- | puedeReservar(Usuario,_) :- |
usuario(Usuario,Prestados,Reservados), | usuario(Usuario,_,Reservados), |
Reservados < 3. | Reservados < 3. |
</code> | </code> |
Una posible solución en haskell: | Una posible solución en haskell: |
<code> | <code> |
| puedeTomarPrestado :: (String,Int,Int) -> (String,Bool,Bool) -> Bool |
| puedeTomarPrestado (_,lp,_) (_,p,r) = lp < 6 && not(p) && not(r) |
| |
| puedeReservar :: (String,Int,Int) -> (String,Bool,Bool) -> Bool |
| puedeReservar (_,_,lr) _ = lr < 3 |
</code> | </code> |
| |
**Bonus Track:** Definir la función ''tieneSegmentoOrdenado :: Int -> [Int] -> Bool'', que dado un entero ''n'' y una lista de enteros, determina si la lista tiene un segmento de longitud mayor o igual a ''n'' cuyos elementos están ordenados de menor a mayor. | **Bonus Track:** Definir la función ''tieneSegmentoOrdenado :: Int -> [Int] -> Bool'', que dado un entero ''n'' y una lista de enteros, determina si la lista tiene un segmento de longitud mayor o igual a ''n'' cuyos elementos están ordenados de menor a mayor. |
| |
Ejemplo: ''tieneSegmentoOrdenado 3 [5,1,4,11,3,2] = true'' | Ejemplo: tieneSegmentoOrdenado 3 [5,1,4,11,3,2] = true. |
''tieneSegmentoOrdenado 4 [5,1,4,11,3,2] = false.'' | tieneSegmentoOrdenado 4 [5,1,4,11,3,2] = false. |
| |
== solución == | == solución == |
| |
| Hemos planteado una posible solución que va recorriendo la lista y va contando cuántos elementos encuentra que estén ordenados de menor a mayor. Cuando el número de elementos ordenados alcanza el número de elementos que pedimos que tenga el segmento, la función termina y devuelve ''True''. Cuando encuentra un elemento que es menor al elemento anterior, deja de contar, es decir, pone el contador en ''1''. Cuando llega a la lista vacía devuelve ''False''. |
| |
| La función principal es ''tieneSegmentoOrdenado'', que lo único que hace es añadir el argumento contador y pasarle todos los argumentos a la función ''cuantosOrdenados''. La función ''cuantosOrdenados'' va comprobando en cada momento si hemos alcanzado la longitud de segmento que estábamos buscando, con la guarda ''c >= n''. Fíjense que si la longitud que buscamos es 0 o 1, nos va a devolver ''True'' sin hacer ningún llamado a la función recursiva. Si no, llama a la función recursiva para que recorra la lista y vaya contando la longitud de los segmentos ordenados que encuentra. |
| |
| La función recursiva es ''cuentaOrdenado'', que va recorriendo la lista. Si encuentra una lista vacía o una lista con un solo elemento, devuelve ''False'', porque llegó al final de la lista sin poder encontrar el segmento que buscaba. Para listas de por lo menos dos elementos, los compara y si el primero es menor que el segundo, entonces suma uno al contador y llama a la función ''cuantosOrdenados'', que comprueba si el segmento que vamos encontrando ya es de la longitud que se pedía en el argumento. Si es así, la función termina con ''True'', si no, vuelve a llamar a ''cuentaOrdenado''. Si el primer elemento es mayor que el segundo, entonces el contador vuelve a su estado inicial, 1, es decir, empieza a contar de nuevo. |
| |
<code> | <code> |
tieneSegmentoOrdenado :: Int -> [Int] -> Bool | tieneSegmentoOrdenado :: Int -> [Int] -> Bool |
| |
cuantosOrdenados :: Int -> Int -> [Int] -> Bool | cuantosOrdenados :: Int -> Int -> [Int] -> Bool |
cuantosOrdenados c n xs | c == n = True | cuantosOrdenados c n xs | c >= n = True |
| otherwise = cuentaOrdenado c n xs | | otherwise = cuentaOrdenado c n xs |
| |
| otherwise = cuentaOrdenado 1 n (y:xs) | | otherwise = cuentaOrdenado 1 n (y:xs) |
</code> | </code> |
| |