Máxima suma de elementos consecutivos
Definir la función
sumaMaxima :: [Integer] -> Integer
tal que (sumaMaxima xs) es el valor máximo de la suma de elementos consecutivos de la lista xs. Por ejemplo,
sumaMaxima [] == 0 sumaMaxima [2,-2,3,-3,4] == 4 sumaMaxima [-1,-2,-3] == 0 sumaMaxima [2,-1,3,-2,3] == 5 sumaMaxima [1,-1,3,-2,4] == 5 sumaMaxima [2,-1,3,-2,4] == 6 sumaMaxima [1..10^6] == 500000500000
Comprobar con QuickCheck que
sumaMaxima xs == sumaMaxima (reverse xs)
Soluciones
import Data.List (inits, tails) import Test.QuickCheck -- 1ª definición -- ============= sumaMaxima1 :: [Integer] -> Integer sumaMaxima1 [] = 0 sumaMaxima1 xs = maximum (0 : map sum [sublista xs i j | i <- [0..length xs - 1], j <- [i..length xs - 1]]) sublista :: [Integer] -> Int -> Int -> [Integer] sublista xs i j = [xs!!k | k <- [i..j]] -- 2ª definición -- ============= sumaMaxima2 :: [Integer] -> Integer sumaMaxima2 [] = 0 sumaMaxima2 xs = sumaMaximaAux 0 0 xs where m = maximum xs sumaMaximaAux :: Integer -> Integer -> [Integer] -> Integer sumaMaximaAux m v [] = max m v sumaMaximaAux m v (x:xs) | x >= 0 = sumaMaximaAux m (v+x) xs | v+x > 0 = sumaMaximaAux (max m v) (v+x) xs | otherwise = sumaMaximaAux (max m v) 0 xs -- 3ª definición -- ============= sumaMaxima3 :: [Integer] -> Integer sumaMaxima3 [] = 0 sumaMaxima3 xs = maximum (map sum (segmentos xs)) -- (segmentos xs) es la lista de los segmentos de xs. Por ejemplo -- segmentos "abc" == ["", "a","ab","abc","b","bc","c"] segmentos :: [a] -> [[a]] segmentos xs = [] : concat [tail (inits ys) | ys <- init (tails xs)] -- 4ª definición -- ============= sumaMaxima4 :: [Integer] -> Integer sumaMaxima4 [] = 0 sumaMaxima4 xs = maximum (concat [scanl (+) 0 ys | ys <- tails xs]) -- Comprobación -- ============ -- La propiedad es prop_sumaMaxima :: [Integer] -> Bool prop_sumaMaxima xs = sumaMaxima2 xs == n && sumaMaxima3 xs == n && sumaMaxima4 xs == n where n = sumaMaxima1 xs -- La comprobación es -- λ> quickCheck prop_sumaMaxima -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- λ> let n = 10^2 in sumaMaxima1 [-n..n] -- 5050 -- (2.10 secs, 390,399,104 bytes) -- λ> let n = 10^2 in sumaMaxima2 [-n..n] -- 5050 -- (0.02 secs, 0 bytes) -- λ> let n = 10^2 in sumaMaxima3 [-n..n] -- 5050 -- (0.27 secs, 147,705,184 bytes) -- λ> let n = 10^2 in sumaMaxima4 [-n..n] -- 5050 -- (0.04 secs, 11,582,520 bytes) prop_inversa :: [Integer] -> Bool prop_inversa xs = sumaMaxima2 xs == sumaMaxima2 (reverse xs)