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)) |
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 |
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 () |
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] |
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" |
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 |
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)) |
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))