# Etiqueta: elems

## Diferencia simétrica

La diferencia simétrica de dos conjuntos es el conjunto cuyos elementos son aquellos que pertenecen a alguno de los conjuntos iniciales, sin pertenecer a ambos a la vez. Por ejemplo, la diferencia simétrica de {2,5,3} y {4,2,3,7} es {5,4,7}.

Definir la función

` diferenciaSimetrica :: Ord a => [a] -> [a] -> [a]`

tal que `(diferenciaSimetrica xs ys)` es la diferencia simétrica de `xs` e `ys`. Por ejemplo,

``` diferenciaSimetrica [2,5,3] [4,2,3,7] == [4,5,7] diferenciaSimetrica [2,5,3] [5,2,3] == [] diferenciaSimetrica [2,5,2] [4,2,3,7] == [3,4,5,7] diferenciaSimetrica [2,5,2] [4,2,4,7] == [4,5,7] diferenciaSimetrica [2,5,2,4] [4,2,4,7] == [5,7]```

#### Soluciones

```import Test.QuickCheck import Data.List ((\\), intersect, nub, sort, union) import qualified Data.Set as S   -- 1ª solución -- ===========   diferenciaSimetrica1 :: Ord a => [a] -> [a] -> [a] diferenciaSimetrica1 xs ys = sort (nub ([x | x <- xs, x `notElem` ys] ++ [y | y <- ys, y `notElem` xs]))   -- 2ª solución -- ===========   diferenciaSimetrica2 :: Ord a => [a] -> [a] -> [a] diferenciaSimetrica2 xs ys = sort (nub (filter (`notElem` ys) xs ++ filter (`notElem` xs) ys))   -- 3ª solución -- ===========   diferenciaSimetrica3 :: Ord a => [a] -> [a] -> [a] diferenciaSimetrica3 xs ys = sort (nub (union xs ys \\ intersect xs ys))   -- 4ª solución -- ===========   diferenciaSimetrica4 :: Ord a => [a] -> [a] -> [a] diferenciaSimetrica4 xs ys = [x | x <- sort (nub (xs ++ ys)) , x `notElem` xs || x `notElem` ys]   -- 5ª solución -- ===========   diferenciaSimetrica5 :: Ord a => [a] -> [a] -> [a] diferenciaSimetrica5 xs ys = S.elems ((xs' `S.union` ys') `S.difference` (xs' `S.intersection` ys')) where xs' = S.fromList xs ys' = S.fromList ys   -- Comprobación de equivalencia -- ============================   -- La propiedad es prop_diferenciaSimetrica :: [Int] -> [Int] -> Bool prop_diferenciaSimetrica xs ys = all (== diferenciaSimetrica1 xs ys) [diferenciaSimetrica2 xs ys, diferenciaSimetrica3 xs ys, diferenciaSimetrica4 xs ys, diferenciaSimetrica5 xs ys]   -- La comprobación es -- λ> quickCheck prop_diferenciaSimetrica -- +++ OK, passed 100 tests.   -- Comparación de eficiencia -- =========================   -- La comparación es -- λ> length (diferenciaSimetrica1 [1..2*10^4] [2,4..2*10^4]) -- 10000 -- (2.34 secs, 10,014,360 bytes) -- λ> length (diferenciaSimetrica2 [1..2*10^4] [2,4..2*10^4]) -- 10000 -- (2.41 secs, 8,174,264 bytes) -- λ> length (diferenciaSimetrica3 [1..2*10^4] [2,4..2*10^4]) -- 10000 -- (5.84 secs, 10,232,006,288 bytes) -- λ> length (diferenciaSimetrica4 [1..2*10^4] [2,4..2*10^4]) -- 10000 -- (5.83 secs, 14,814,184 bytes) -- λ> length (diferenciaSimetrica5 [1..2*10^4] [2,4..2*10^4]) -- 10000 -- (0.02 secs, 7,253,496 bytes)```

El código se encuentra en GitHub.

La elaboración de las soluciones se describe en el siguiente vídeo

#### Nuevas soluciones

• En los comentarios se pueden escribir nuevas soluciones.
• El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

## Clausura respecto de una operación binaria

Se dice que una operador @ es interno en un conjunto A si al @ sobre elementos de A se obtiene como resultado otro elemento de A. Por ejemplo, la suma es un operador interno en el conjunto de los números naturales pares.

La clausura de un conjunto A con respecto a un operador @ es el menor conjunto B tal que A está contenido en B y el operador @ es interno en el conjunto B. Por ejemplo, la clausura del conjunto {2} con respecto a la suma es el conjunto de los números pares positivos:

` {2, 4, 6, 8, ...} = {2*k | k <- [1..]}`

Definir la función

` clausuraOperador :: (Int -> Int -> Int) -> Set Int -> Set Int`

tal que (clausuraOperador op xs) es la clausura del conjunto xs con respecto a la operación op. Por ejemplo,

``` clausuraOperador gcd (fromList [6,9,10]) == fromList [1,2,3,6,9,10] clausuraOperador gcd (fromList [42,70,105]) == fromList [7,14,21,35,42,70,105] clausuraOperador lcm (fromList [6,9,10]) == fromList [6,9,10,18,30,90] clausuraOperador lcm (fromList [2,3,5,7]) == fromList [2,3,5,6,7,10,14,15,21,30,35,42,70,105,210]```

#### Soluciones

```import Prelude hiding (map) import Data.Set ( Set , elems , fromList , map , notMember , union , unions )   -- 1ª definición clausuraOperador :: (Int -> Int -> Int) -> Set Int -> Set Int clausuraOperador op = until (\ xs -> null [(x,y) | x <- elems xs, y <- elems xs, notMember (op x y) xs]) (\ xs -> union xs (fromList [op x y | x <- elems xs, y <- elems xs]))   -- 2ª definición clausuraOperador2 :: (Int -> Int -> Int) -> Set Int -> Set Int clausuraOperador2 op = until ((==) <*> g) g where g ys = unions [map (`op` y) ys | y <- elems ys]```