Herramientas de usuario

Herramientas del sitio


introalg:taller07_2

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
introalg:taller07_2 [2007/04/17 15:30] nicolaswintroalg:taller07_2 [2018/08/10 03:03] (actual) – editor externo 127.0.0.1
Línea 122: Línea 122:
   Main> map alMenos2' [ [], [1..1], [1..2], [1..3], [1..4], [1..10000] ]   Main> map alMenos2' [ [], [1..1], [1..2], [1..3], [1..4], [1..10000] ]
   [False,False,True,True,True,True]   [False,False,True,True,True,True]
 +
  
  
Línea 155: Línea 156:
      
   Program error: No hay cabeza   Program error: No hay cabeza
 +  
   Main> ordenaCabeza (take 10 (repeat (2,1)))   Main> ordenaCabeza (take 10 (repeat (2,1)))
   (1,2)   (1,2)
 +
 +
  
 ===== Dividiendo el problema en partes ===== ===== Dividiendo el problema en partes =====
Línea 194: Línea 197:
 </code> </code>
  
-Y hasta podemos generalizar las funciones //unidad, decena, etc.// en una que nos dé el dígito n-ésimo de la representación decimal, pero para eso necesitamos usar funciones recursivas y eso lo haremos... en la próxima clase!+Siempre es conveniente ser desconfiado y probamos que ambas funciones sean iguales en el rango //[0,9999]// 
 + 
 +  Main> filter pip [0..9999] == filter pip' [0..9999] 
 +  True 
 + 
 +Y hasta podemos generalizar las funciones //unidad, decena, etc.// en una que nos dé el dígito n-ésimo de la representación decimal, pero para eso necesitamos usar **funciones recursivas**.\\ 
 +Eso será tema de la próxima clase, pero veamos de todas maneras la "pinta" de la función. 
 + 
 +<code> 
 +digitos :: Int -> [Int] 
 +digitos 0 = [] 
 +digitos n = n `mod` 10 : (digitos (n `div` 10)) 
 +</code> 
 + 
 +La probamos para ver como opera 
 + 
 +  Main> digitos 0 
 +  [] 
 +  Main> digitos 1 
 +  [1] 
 +  Main> digitos 10 
 +  [0,1] 
 +  Main> digitos 120 
 +  [0,2,1] 
 +  Main> digitos 123123123 
 +  [3,2,1,3,2,1,3,2,1] 
 + 
 + 
 + 
  
 ==== Otro ejemplo ==== ==== Otro ejemplo ====
Línea 203: Línea 235:
  
 <code> <code>
-descuento :: (Int,Bool) -> (Float,Int,Float) +descuento :: (Float,Bool) -> (Float,Float,Float) 
--- argumento: una tupla (Int,Bool) que representa el monto (Int) y si tenemos tickets (Bool) +-- argumento: un par que representa el monto (Float) y si tenemos tickets (Bool) 
--- resultado: una tresupla (Float,Int,Float) que representa el monto total, +-- resultado: una tresupla (Float,Float,Float) que representa el monto total, 
 --            restando el descuento correspondiente, el número de puntos  --            restando el descuento correspondiente, el número de puntos 
 --            y el descuento en tickets, respectivamente. --            y el descuento en tickets, respectivamente.
  
-descuento x y | x == 257 && y == True = ( x - 0.2*x , 10*x, 0.1*x) +descuento (x,y| x == 257 && y     = ( x - 0.2*x , 10*x, 0.1*x) 
-              | x == 257 && y == False = ( x - 0.2*x , 10*x, 0) +                | x == 257 && not y = ( x - 0.2*x , 10*x, 0) 
-              | x == 350 && y == True = ( x - 0.2*x , 10*x, 0.1*x) +                | x == 350 && y     = ( x - 0.2*x , 10*x, 0.1*x) 
-              | x == 350 && y == False = ( x - 0.2*x , 10*x, 0) +                | x == 350 && not y = ( x - 0.2*x , 10*x, 0) 
-              | x == 489 && y == True = ( x - 0.2*x , 10*x, 0.1*x) +                | x == 489 && y     = ( x - 0.2*x , 10*x, 0.1*x) 
-              | x == 489 && y == False = ( x - 0.2*x , 10*x, 0) +                | x == 489 && not y = ( x - 0.2*x , 10*x, 0) 
-              | x > 1000 && y == True = ( x - 0.2*x , 10*x, 0.1*x) +                | x > 1000 && y     = ( x - 0.2*x , 10*x, 0.1*x) 
-              | x > 1000  && y == False = ( x - 0.2*x , 10*x, 0) +                | x > 1000 && not y = ( x - 0.2*x , 10*x, 0) 
-              | x == 768 && y == True = ( x - 0.2*x , 10*x, 0.1*x) +                | x == 768 && y     = ( x - 0.2*x , 10*x, 0.1*x) 
-              | x == 768 && y == False = ( x - 0.2*x , 10*x, 0) +                | x == 768 && not y = ( x - 0.2*x , 10*x, 0) 
-              | x == 999 && y == True = ( x - 0.2*x , 10*x, 0.1*x) +                | x == 999 && y     = ( x - 0.2*x , 10*x, 0.1*x) 
-              | x == 573 && y == False = ( x - 0.2*x , 10*x, 0) +                | x == 573 && not y = ( x - 0.2*x , 10*x, 0) 
-              | x > 500 && x <= 1000 && y == True = ( x - 0.15*x , 5*x, 0.05*x) +                | x > 500 && x <= 1000 && y      = ( x - 0.15*x , 5*x, 0.05*x) 
-              | x > 500 && x <= 1000 && y == False = ( x - 0.15*x , 5*x, 0) +                | x > 500 && x <= 1000 && not  = ( x - 0.15*x , 5*x, 0) 
-              | x > 200 && x <= 500 && y == True = ( x - 0.1*x , 2*x, 0.02*x) +                | x > 200 && x <= 500  && y      = ( x - 0.1*x , 2*x, 0.02*x) 
-              | x > 200 && x <= 500 && y == False = ( x - 0.1*x , 2*x, 0) +                | x > 200 && x <= 500  && not  = ( x - 0.1*x , 2*x, 0) 
-              | x <= 200 = ( x , x , 0 )+                | x <= 200 = ( x , x , 0)
 </code> </code>
  
Línea 231: Línea 263:
  
 <code> <code>
-descuento :: (Int,Bool) -> (Float,Int,Float) +descuento:: (Float,Bool) -> (Float,Float,Float) 
-descuento (x,y) | x == 257 || x == 350 || x == 489 || x == 768 || x == 999 || x == 573 = descuento20 (x,y) +descuento(x,y) | x == 257 || x == 350 || x == 489 || x == 768 || x == 999 || x == 573 = descuento20 (x,y) 
-                | x > 1000 = descuento20 (x,y) +                 | x > 1000 = descuento20 (x,y) 
-                | x > 500 && x <= 1000 = descuento15 (x,y) +                 | x > 500 && x <= 1000 = descuento15 (x,y) 
-                | x > 200 && x <= 500 = descuento10 (x,y) +                 | x > 200 && x <= 500 = descuento10 (x,y) 
-                | x <= 200 = descuento0 (x,y)+                 | x <= 200 = descuento0 (x,y)
  
-descuento20 :: (Int,Bool) -> (Float,Int,Float)+descuento20 :: (Float,Bool) -> (Float,Float,Float)
 descuento20 (x,y) | y == True = ( x - 0.2*x , 10*x, 0.1*x) descuento20 (x,y) | y == True = ( x - 0.2*x , 10*x, 0.1*x)
                   | y == False = ( x - 0.2*x , 10*x, 0)                   | y == False = ( x - 0.2*x , 10*x, 0)
  
-descuento15 :: (Int,Bool) -> (Float,Int,Float)+descuento15 :: (Float,Bool) -> (Float,Float,Float)
 descuento15 (x,y) | y == True = ( x - 0.15*x , 5*x, 0.05*x) descuento15 (x,y) | y == True = ( x - 0.15*x , 5*x, 0.05*x)
                   | y == False = ( x - 0.15*x , 5*x, 0)                   | y == False = ( x - 0.15*x , 5*x, 0)
  
-descuento10 :: (Int,Bool) -> (Float,Int,Float)+descuento10 :: (Float,Bool) -> (Float,Float,Float)
 descuento10 (x,y) | y == True = ( x - 0.1*x , 2*x, 0.02*x) descuento10 (x,y) | y == True = ( x - 0.1*x , 2*x, 0.02*x)
                   | y == False = ( x - 0.1*x , 2*x, 0)                   | y == False = ( x - 0.1*x , 2*x, 0)
  
-descuento0 :: (Int,Bool) -> (Float,Int,Float) +descuento0 :: (Float,Bool) -> (Float,Float,Float) 
-descuento0 (x,y) = ( x , x , 0 )+descuento0 (x,y) = ( x , x , 0)
 </code> </code>
  
  
-==== Algo un poco más ordenado ====+ 
  
  
 ===== Estilo de Código (coding style) ===== ===== Estilo de Código (coding style) =====
 +
 +
 +
 +
  
 ==== Reglas de sangrado (layout) (distribución) ==== ==== Reglas de sangrado (layout) (distribución) ====
Línea 270: Línea 307:
   * el código que forma parte de una expresión (o bloque) tiene que indentarse más adentro que la línea que contiene el principio de esa expresión.   * el código que forma parte de una expresión (o bloque) tiene que indentarse más adentro que la línea que contiene el principio de esa expresión.
  
-Por ejemplo, cuando usamos una lista de instrucciones de la misma clase dentro de una función, deben estar todas indentadas a la misma altura, como si estuvierna formando una **columna**, o, si no, más adentro. Vean en el siguiente ejemplo como "//frente//", "//lado//" y "//tapa//" están todas a la misma altura de indentación, formando una columna, y más indentadas que la palabra "//where//", que introduce la expresión dentro de la cual se encuentran:+Por ejemplo, cuando usamos una lista de instrucciones de la misma clase dentro de una función, deben estar todas indentadas a la misma altura, como si estuvieran formando una **columna**, o, si no, más adentro. Vean en el siguiente ejemplo como "//frente//", "//lado//" y "//tapa//" están todas a la misma altura de indentación, formando una columna, y más indentadas que la palabra "//where//", que introduce la expresión dentro de la cual se encuentran:
  
-  area.a.b.c = 2*frente + 2*lado + 2*tapa+  area a b c = 2*frente + 2*lado + 2*tapa
      where      where
         frente = a*b         frente = a*b
Línea 281: Línea 318:
   PREGUNTA: ¿Cómo podemos escribir esta función usando puntuación en lugar de indentación?   PREGUNTA: ¿Cómo podemos escribir esta función usando puntuación en lugar de indentación?
  
-Esto estaría mal si lo escribiéramos de la siguiente forma:+Esto sigue siendo válido si escribimos:
  
-  area.a.b.c = 2*frente + 2*lado + 2*tapa+  area a b c = 2*frente + 2*lado + 2*tapa
      where      where
      frente = a*b      frente = a*b
Línea 289: Línea 326:
      tapa = a*c      tapa = a*c
  
-Y también si lo escribiéramos así:+Pero no cuando las //definiciones locales// están en la misma columna que la definición global de ''area''.
  
-  area.a.b.c = 2*frente + 2*lado + 2*tapa+  area a b c = 2*frente + 2*lado + 2*tapa
      where      where
-    frente = a*b +  frente = a*b 
-    lado = b*c +  lado = b*c 
-    tapa = a*c+  tapa = a*c 
 + 
 +Simplemente no sabe que el ''b'' de la definición de frente es el parámetro ''b'' de ''area''
 + 
 +  Main> :e 
 +  ERROR "1.hs":69 - Undefined variable "b" 
  
 Para ver más ejemplos, vayan al [[http://en.wikibooks.org/wiki/Haskell/Indentation|apartado sobre indentación]] del [[http://en.wikibooks.org/wiki/Haskell/|wikibook de Haskell]]. Para ver más ejemplos, vayan al [[http://en.wikibooks.org/wiki/Haskell/Indentation|apartado sobre indentación]] del [[http://en.wikibooks.org/wiki/Haskell/|wikibook de Haskell]].
Línea 301: Línea 344:
 Para saber más, vean la [[http://haskell.org/onlinereport/lexemes.html#lexemes-layout|descripción informal]] o [[http://haskell.org/onlinereport/syntax-iso.html#layout|más formal]] de este tema en el [[http://haskell.org/onlinereport/|Haskell Report]]. Para saber más, vean la [[http://haskell.org/onlinereport/lexemes.html#lexemes-layout|descripción informal]] o [[http://haskell.org/onlinereport/syntax-iso.html#layout|más formal]] de este tema en el [[http://haskell.org/onlinereport/|Haskell Report]].
  
-Y ya que estamos, sepan que toda línea que comienza por dos guiones (o signos "menos") no será interpretada por el intérprete de Haskell, de esta forma se pueden introducir comentarios en los programas.+Y ya que estamos, sepan que toda **línea** que comienza por dos guiones (o signos "menos") no será interpretada por el intérprete de Haskell, de esta forma se pueden introducir comentarios en los programas. 
 +Y para evitar que se interpreten **bloques completos**, a éstos los demarcamos con ''{- bloque -}'' 
 + 
 +<code> 
 +-- Nada de esto se toma 
 +{- Y esto 
 +   tampoco! 
 +-} 
 +</code> 
  
 ==== Case sensitiveness (sensibilidad a la caja) ==== ==== Case sensitiveness (sensibilidad a la caja) ====
Línea 312: Línea 364:
  
   * los nombres de **funciones y variables** comienzan con **minúscula**   * los nombres de **funciones y variables** comienzan con **minúscula**
 +
 +
 +
 +
 +==== Nombres de variables ====
 +
 +En general se intenta que el código sea auto explicativo, en el sentido que baste con leerlo para comprender como funciona.
 +Algo que resulta muy sencillo y útil es dar nombres significativos a las variables.
 +Podríamos haber escrito la función área de la siguiente manera.
 +
 +  area a1 a2 a3 = 2*a4 + 2*a5 + 2*a6
 +     where
 +        a4 = a1*a2
 +        a5 = a2*a3
 +        a6 = a1*a3
 +
 +o bien de manera equivalente e igualmente eficiente, pero mucho más comprensible:
 +
 +  area b a p = 2*frente + 2*lado + 2*tapa
 +     where
 +        frente = b * a
 +        lado = p * a
 +        tapa = b * p
 +
  
 ===== Ejercicios ===== ===== Ejercicios =====
Línea 324: Línea 400:
   probar con [1,2,3], con [3,3,3] y con [].   probar con [1,2,3], con [3,3,3] y con [].
  
-  * Definir una función //esVaciaOPrimer0.xs//, //esVaciaOPrimer0 : [a] -> Bool// que dada una lista //xs// decida si //xs// es vacía o bien su primer elemento es 0.+  * Definir una función //esVaciaOPrimer0.xs//, //esVaciaOPrimer0 : [Int] -> Bool// que dada una lista //xs// decida si //xs// es vacía o bien su primer elemento es 0.
  
   probar con [1,2,3], con [3,3,3], con [0], con [0,1] y con [].   probar con [1,2,3], con [3,3,3], con [0], con [0,1] y con [].
  
-  * Definir una función //segundoEssegundo.(x,y).zs//, //segundoEssegundo : (Int,Int) -> [Int] -> Bool// que dada una tupla de enteros //(x,y)// y una lista de enteros //zs// comprueba si el segundo elemento de la tupla es igual al segundo elemento de la lista.+  * Definir una función //segundoEsSegundo.(x,y).zs//, //segundoEsSegundo : (Int,Int) -> [Int] -> Bool// que dada una tupla de enteros //(x,y)// y una lista de enteros //zs// comprueba si el segundo elemento de la tupla es igual al segundo elemento de la lista.
  
   probar con (1,2) y [3,2,4,5], (0,0) y [], (1,2) y [2,3,4,5].   probar con (1,2) y [3,2,4,5], (0,0) y [], (1,2) y [2,3,4,5].
  
-  * Definir una función //recortaDia.xs//, //recortaDia : [Char] -> [Char]// que dada una lista de caracteres //xs//, comprueba si las letras de la lista forman el nombre de un día de la semana, si es así, si el día es de diario, devuelven la primera letra solamente, en cambio, si el día es de fin de semana, devuelven el nombre del día completo.+  * Definir una función //recortaDia.xs//, //recortaDia : [Char] -> [Char]// que dada una lista de caracteres //xs//, 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! Ayuda: fíjense que el resultado siempre debe ser una lista de caracteres!
  
introalg/taller07_2.1176823857.txt.gz · Última modificación: 2018/08/10 03:03 (editor externo)