Menu Close

Notas de evaluación acumulada

La evaluación acumulada, las notas se calculan recursivamente con la siguiente función

   N(1) = E(1)
   N(k) = máximo(E(k), 0.4*N(k-1)+0.6*E(k))

donde E(k) es la nota del examen k. Por ejemplo, si las notas de los exámenes son [3,7,6,3] entonces las acumuladas son [3.0,7.0,6.4,4.4]

Las notas e los exámenes se encuentran en ficheros CSV con los valores separados por comas. Cada línea representa la nota de un alumno, el primer valor es el identificador del alumno y los restantes son sus notas. Por ejemplo, el contenido de examenes.csv es

   juaruigar,3,7,9,3
   evadialop,3,6,7,4
   carrodmes,0,9,8,7

Definir las funciones

   acumuladas      :: [Double] -> [Double]
   notasAcumuladas :: FilePath -> FilePath -> IO ()

tales que

  • (acumuladas xs) es la lista de las notas acumuladas (redondeadas con un decimal) de los notas de los exámenes xs. Por ejemplo,
     acumuladas [2,5]      ==  [2.0,5.0]
     acumuladas [5,2]      ==  [5.0,3.2]
     acumuladas [3,7,6,3]  ==  [3.0,7.0,6.4,4.4]
     acumuladas [3,6,7,3]  ==  [3.0,6.0,7.0,4.6]
  • (notasAcumuladas f1 f2) que escriba en el fichero f2 las notas acumuladas correspondientes a las notas de los exámenes del fichero f1. Por ejemplo, al evaluar
     notasAcumuladas "examenes.csv" "acumuladas.csv"

escribe en el fichero acumuladas.csv

     juaruigar,3.0,7.0,9.0,5.4
     evadialop,3.0,6.0,7.0,5.2
     carrodmes,0.0,9.0,8.4,7.6

Soluciones

import Text.CSV
import Data.Either
 
-- Definicioń de acumuladas
-- ========================
 
acumuladas :: [Double] -> [Double]
acumuladas = reverse . aux . reverse
  where aux []     = []
        aux [x]    = [x]
        aux (x:xs) = conUnDecimal (max x (0.6*x+0.4*y)) : y : ys 
          where (y:ys) = aux xs
 
--    conUnDecimal 7.26  ==  7.3
--    conUnDecimal 7.24  ==  7.2
conUnDecimal :: Double -> Double
conUnDecimal x = fromIntegral (round (10*x)) / 10
 
-- 1ª definición de notasAcumuladas
-- ================================
 
notasAcumuladas :: FilePath -> FilePath -> IO ()
notasAcumuladas f1 f2 = do
  cs <- readFile f1
  writeFile f2 (unlines (map ( acumuladaACadena
                             . notaAAcumuladas
                             . listaANota
                             . cadenaALista
                             )
                             (contenidoALineasDeNotas cs)))
 
--   λ> contenidoALineasDeNotas "juaruigar,3,7,6,3\nevadialop,3,6,7,3\n\n  \n"
--   ["juaruigar,3,7,6,3","evadialop,3,6,7,3"]
contenidoALineasDeNotas :: String -> [String]
contenidoALineasDeNotas = filter esLineaDeNotas . lines
  where esLineaDeNotas = elem ','
 
--    cadenaALista "a,b c,d"            ==  ["a","b c","d"]
--    cadenaALista "juaruigar,3,7,6,3"  ==  ["juaruigar","3","7","6","3"]
cadenaALista :: String -> [String]
cadenaALista cs
  | tieneComas cs = d : cadenaALista ds
  | otherwise     = [cs]
  where (d,_:ds)   = span (/=',') cs
        tieneComas = elem ','
 
--    λ> listaANota ["juaruigar","3","7","6","3"]
--    ("juaruigar",[3.0,7.0,6.0,3.0])
listaANota :: [String] -> (String,[Double])
listaANota (x:xs) = (x,map read xs)
 
--   λ> notaAAcumuladas ("juaruigar",[3.0,7.0,6.0,3.0])
--   ("juaruigar",[3.0,7.0,6.4,4.4])
notaAAcumuladas :: (String,[Double]) -> (String,[Double])
notaAAcumuladas (x,xs) = (x, acumuladas xs)
 
--    λ> acumuladaACadena ("juaruigar",[3.0,7.0,6.4,4.4])
--    "juaruigar,3.0,7.0,6.4,4.4"
acumuladaACadena :: (String,[Double]) -> String
acumuladaACadena (x,xs) =
  x ++ "," ++ tail (init (show xs))
 
-- 2ª definición de notasAcumuladas
-- ================================
 
notasAcumuladas2 :: FilePath -> FilePath -> IO ()
notasAcumuladas2 f1 f2 = do
  cs <- readFile f1
  let (Right csv) = parseCSV f1 cs
  let notas = [xs | xs <- csv, length xs > 1]
  writeFile f2 (unlines (map ( acumuladaACadena
                             . notaAAcumuladas
                             . listaANota
                             )
                             notas))
Avanzado

2 soluciones de “Notas de evaluación acumulada

  1. guigornun
     
    import Data.Char
    import Text.Printf
     
    acumuladas :: [Double] -> [Double]
    acumuladas (a:[]) = [a]
    acumuladas (a:b:cs) = a : acumuladas ((redondea (max b (0.6*b + 0.4*a))):cs) 
     
    notasAcumuladas :: FilePath -> FilePath -> IO ()
    notasAcumuladas f1 f2 = do
      xs <- readFile f1
      writeFile f2 (transforma (map (acumula) (lines xs)))
     
    -- Funciones auxiliares
     
    redondea x = (fromIntegral (round (x*10))) / 10
     
    -- La función (acumula cs) toma una expresión de la forma "nombre,E(1),E(2),E(3),E(4)"
    -- y la transforma en el par ("nombre",[N(i)]), calculando las notas acumuladas.
    -- acumula "juaruigar,3,7,9,3" == ("juaruigar",[3.0,7.0,9.0,5.4])
    -- acumula "evadialop,3,6,7,4" == ("evadialop",[3.0,6.0,7.0,5.2])
     
    acumula cs = (init (takeWhile (not.isDigit) cs),acumuladas (map (fromIntegral.digitToInt) (aux (dropWhile (not.isDigit) cs))))
     where aux [] = []
           aux (d:ds) | isDigit d = d:aux ds
                      | otherwise = aux ds
     
    -- La función (transforma xs) toma una expresión salida de la función (acumula
    -- cs) y lo transforma en una cadena legible por el fichero
    -- transforma [("juaruigar",[3.0,7.0,9.0,5.4]),("evadialop",[3.0,6.0,7.0,5.2])]
    -- == "juaruigar,3.0,7.0,9.0,5.4nevadialop,3.0,6.0,7.0,5.2n"
     
    transforma [] = []
    transforma ((nombre,xs):ac) = nombre ++ ","++ aux xs ++ "n" ++ transforma ac
     where aux (x:[]) = show x
           aux (x:xs) = show x ++ "," ++ aux xs
  2. angruicam1
    import Text.CSV
    import Data.Csv
    import Data.Char
    import Text.Printf
    import qualified Data.ByteString.Lazy as BSL
     
    acumuladas :: [Double] -> [Double]
    acumuladas xs = [read (printf "%.1f" n) | n <- aux 0 xs]
      where aux z (y:ys) = k : aux k ys
              where k = max y (0.4*z+0.6*y)
            aux _ _      = []
     
    notasAcumuladas :: FilePath -> FilePath -> IO ()
    notasAcumuladas f1 f2 = do
      input <- readFile f1
      let csv = parseCSV f1 input
      either handleError (doWork f2) csv
     
    -- (handleError csv) devuelve un mensaje en caso de que el archivo csv
    -- no tenga la extensión .csv. Por ejemplo,
    --    λ> notasAcumuladas "notasDeEvaluacionAcumulada.hs" "acumuladas.csv"
    --    not a CSV
    handleError :: t -> IO ()
    handleError csv = putStrLn "not a CSV"
     
    doWork :: FilePath -> [[String]] -> IO ()
    doWork name csv =
      (export name -- Exporta a name.csv
       . map ((x:xs) -> x : map show (acumuladas (map read xs))))
      -- Cálcula las notas acumuladas
      (filter (any isLetter . head) csv) -- Elimina las partes sobrantes
     
    export :: ToRecord a => FilePath -> [a] -> IO ()
    export name csv = BSL.writeFile name $ encode csv

Escribe tu solución

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.