UTNianos

Versión completa: Ejercicios de Recursividad
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
Holaaa a todos!

Tengo un problema con estos ejercicios de recursividad:

1) Definir la función sinExtremos, que recibe una lista de números y devuelve lo que resulta de sacar los números máximo y el mínimo. P.ej. se espera que
Main> sinExtremos [38,3,86,341,29,42,35,9]
[38,86,29,42,35,9].
Nota: Si la lista tiene menos de dos elementos, sinExtremos debe devolver la lista vacía.

2) 1.12.2. Definir la función sinPuntas/2, que generaliza sinExtremos diciendo cuántos quiero sacar
de cada punta. P.ej. se espera que
Main> sinPuntas 2 [38,3,86,341,29,42,35,9]
[38,29,42,35].
¿Cómo se puede definir sinExtremos usando sinPuntas?
Para el primero, hice esto:


sinExtremos [] = []
sinExtremos (x:y:[]) = []
sinExtremos (x:xs)
|x/=(maximum (x:xs)) && x/=(minimum (x:xs))=(x : sinExtremos xs)
|otherwise = sinExtremos xs


Pero me devuelve la lista vacía =(

Lo pude resolver por lista por compresión, asi:


sinExtremos' lista = [x | x <- lista, x /= (maximum lista), x /= (minimum lista)]


Pero la guía es de Recursividad, y no se me ocurre cómo hacerlo.

Muchas gracias por su ayuda!
No tengo mucha idea de esto (recién mañana practico un poco, ahora estoy más digeriendo conceptos), pero leyendo por lo alto:
Nota: Si la lista tiene menos de dos elementos, sinExtremos debe devolver la lista vacía.

Dice MENOS, no MENOS O IGUAL A DOS, como quisiste hacer acá:
2 | sinExtremos (x:y:[]) = []


Por eso debe ser que te devuelve la lista vacía.
Tenés razón en que están mal los casos base, pero no es por eso que me devuelve a lista vacia. Es porque no sé cómo hacer para que la función se deje de ejecutar una vez que ya saco el maximo y el mínimo pro primer vez, lo saca una vez, y despues vuelve a sacarlos de la lista resultante, y así hasta que queda la lista vacía wall
Che y si en vez de hacer todo junto, lo haces por parte. Dudo que sea la forma, pero primero le sacas el minimo y despues el maximo a la lista que resulta
Estem, yo lo hice con guardas. Te lo aceptan mas con pattern matching pero por ahi te sirve :

-- Quito los extremos

sinExtremos listaNum
| (listaNum == []) || (tail listaNum == []) || (drop 2 listaNum == []) = []
| (head listaNum /= foldl1 (max) listaNum) && (head listaNum /= foldl1 (min) listaNum) = (take 1 listaNum) ++ sinExtremos (tail listaNum)
| (head listaNum == foldl1 (max) listaNum) || (head listaNum == foldl1 (min) listaNum) =
sinExtremos (tail listaNum ++ take 1 listaNum)

-- El primer caso es si la lista tiene dos o menos elementos, que devuelve lista vacía. El segundo si el primer elemento no es máximo ni mínimo, y el tercero si lo es. Quedó HORRIBLE, pero compila.

-- El anterior generalizado

sinPuntas n listaNum | ((drop (2 * n) listaNum) == []) = []
| (head listaNum /= foldl1 (max) listaNum) && (head listaNum /= foldl1 (min) listaNum) = (take 1 listaNum) ++ sinPuntas n (tail listaNum)
| (head listaNum == foldl1 (max) listaNum) || (head listaNum == foldl1 (min) listaNum) =
sinPuntas n (tail listaNum ++ take 1 listaNum)
Así lo terminé resolviendo: la clave es que la funcion ordenarBis recibe la lista dos veces, una para borrar los extremos, y la otra para comparar.


ordenar :: Ord a => [a]->[a]
ordenar [] = []
ordenar xs = ordenarBis xs xs


ordenarBis :: Ord a => [a] -> [a] -> [a]
ordenarBis [] _ = []
ordenarBis (x:xs) ys
| x==maximo(ys) = ordenarBis xs ys
| x==minimo(ys) = ordenarBis xs ys
| otherwise = x:(ordenarBis xs ys)


(09-05-2013 15:28)rm1216 escribió: [ -> ]Estem, yo lo hice con guardas. Te lo aceptan mas con pattern matching pero por ahi te sirve :

-- Quito los extremos

sinExtremos listaNum
| (listaNum == []) || (tail listaNum == []) || (drop 2 listaNum == []) = []
| (head listaNum /= foldl1 (max) listaNum) && (head listaNum /= foldl1 (min) listaNum) = (take 1 listaNum) ++ sinExtremos (tail listaNum)
| (head listaNum == foldl1 (max) listaNum) || (head listaNum == foldl1 (min) listaNum) =
sinExtremos (tail listaNum ++ take 1 listaNum)

-- El primer caso es si la lista tiene dos o menos elementos, que devuelve lista vacía. El segundo si el primer elemento no es máximo ni mínimo, y el tercero si lo es. Quedó HORRIBLE, pero compila.

-- El anterior generalizado

sinPuntas n listaNum | ((drop (2 * n) listaNum) == []) = []
| (head listaNum /= foldl1 (max) listaNum) && (head listaNum /= foldl1 (min) listaNum) = (take 1 listaNum) ++ sinPuntas n (tail listaNum)
| (head listaNum == foldl1 (max) listaNum) || (head listaNum == foldl1 (min) listaNum) =
sinPuntas n (tail listaNum ++ take 1 listaNum)

Esto está bien, pero ¡guarda! estás abriendo la lista siempre en cabeza y cola, aca debés usar pattern matching o te lo van a marcar en el parcial.
URLs de referencia