Menu Close

División según una propiedad

Enunciado

Definir la función

   divideSegun :: (a -> Bool) -> [a] -> [[a]]

tal que (divideSegun p xs) es la lista de los segmentos de xs cuyos elementos no cumplen la propiedad p. Por ejemplo,

   divideSegun even [3,5,2,7,6,8,9,1]  ==  [[3,5],[7],[9,1]]
   divideSegun odd  [3,5,2,7,6,8,9,1]  ==  [[2],[6,8]]

Comprobar con QuickCheck que, para cualquier lista xs de números enteros, la concatenación de los elementos de (divideSegun even xs) es la lista de los elementos de xs que no son pares.

Soluciones

import Test.QuickCheck
 
divideSegun :: (a -> Bool) -> [a] -> [[a]]
divideSegun p xs 
    | null ys   = []
    | otherwise = ys : divideSegun p zs
    where (ys,zs) = break p (dropWhile p xs)
 
-- La propiedad es
prop_divideSegun :: [Int] -> Bool
prop_divideSegun xs =
    concat (divideSegun even xs) == filter (not . even) xs
 
-- La comprobación es 
--    ghci> quickCheck prop_divideSegun
--    +++ OK, passed 100 tests.

3 soluciones de “División según una propiedad

  1. M Miranda
    divideSegun p xs = eliminaVacio p (agrupaPropiedad p xs)
     
    agrupaPropiedad p [] = [[]]
    agrupaPropiedad p xs 
        | not (null (primeraLista p xs)) = 
            [primeraLista p xs] ++ 
            agrupaPropiedad p (xs \ (primeraLista p xs))
        | otherwise = 
            [primeraLista p xs] ++ 
            agrupaPropiedad p (tail (xs \ (primeraLista p xs)))
     
    primeraLista p [] = []
    primeraLista p (x:xs) | not (p x) = [x] ++ primeraLista p xs
                          | otherwise = []
     
    eliminaVacio p [] = []
    eliminaVacio p (xs:xss) | null xs   = eliminaVacio p xss
                            | otherwise = [xs] ++ eliminaVacio p xss
  2. jneira

    Con Data.List.Split y sus combinadores queda mas elegante

    divideSegun :: (a -> Bool) -> [a] -> [[a]]
    divideSegun _ [] = []
    divideSegun p xs = yz : divideSegun p nxt
       where (yz,zs) = break p xs
             nxt = dropWhile p zs
     
    divideSegun2 :: (a -> Bool) -> [a] -> [[a]]
    divideSegun2 = split . dropBlanks . dropDelims . whenElt
  3. angruicam1
    import Test.QuickCheck
     
    divideSegun :: (a -> Bool) -> [a] -> [[a]]
    divideSegun  _ []     = []
    divideSegun p (x:xs) | p x       = divideSegun p xs
                         | otherwise = (x : takeWhile (not . p) xs) : divideSegun
                           p (dropWhile (not . p) xs)
     
    prop_divideSegun :: [Int] -> Bool
    prop_divideSegun xs = filter odd xs == concat (divideSegun even xs)
     
    -- La comprobación es
    --    λ> quickCheck prop_divideSegun
    --    +++ OK, passed 100 tests

Escribe tu solución

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