I1M2014: Ejercicios de operaciones con conjuntos en Haskell
En la segunda parte de la clase de hoy de Informática de 1º del Grado en Matemáticas hemos comentado las soluciones de los ejercicios sobre conjuntos de la 19ª relación.
Los ejercicios y su solución se muestran a continuación
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
-- --------------------------------------------------------------------- -- Introducción -- -- --------------------------------------------------------------------- -- El objetivo de esta relación de ejercicios es definir operaciones -- entre conjuntos, representados mediante listas ordenadas sin -- repeticiones, explicado en el tema 17 cuyas transparencias se -- encuentran en -- http://www.cs.us.es/~jalonso/cursos/i1m-14/temas/tema-17t.pdf -- --------------------------------------------------------------------- -- § Librerías auxiliares -- -- --------------------------------------------------------------------- {-# LANGUAGE FlexibleInstances #-} import Test.QuickCheck -- --------------------------------------------------------------------- -- § Representación de conjuntos y operaciones básicas -- -- --------------------------------------------------------------------- -- Los conjuntos como listas ordenadas sin repeticiones. newtype Conj a = Cj [a] deriving Eq -- Procedimiento de escritura de los conjuntos. instance (Show a) => Show (Conj a) where showsPrec _ (Cj s) cad = showConj s cad showConj [] cad = showString "{}" cad showConj (x:xs) cad = showChar '{' (shows x (showl xs cad)) where showl [] cad = showChar '}' cad showl (x:xs) cad = showChar ',' (shows x (showl xs cad)) -- Ejemplo de conjunto: -- ghci> c1 -- {0,1,2,3,5,7,9} c1, c2, c3, c4 :: Conj Int c1 = foldr inserta vacio [2,5,1,3,7,5,3,2,1,9,0] c2 = foldr inserta vacio [2,6,8,6,1,2,1,9,6] c3 = Cj [2..100000] c4 = Cj [1..100000] -- vacio es el conjunto vacío. Por ejemplo, -- ghci> vacio -- {} vacio :: Conj a vacio = Cj [] -- (esVacio c) se verifica si c es el conjunto vacío. Por ejemplo, -- esVacio c1 == False -- esVacio vacio == True esVacio :: Conj a -> Bool esVacio (Cj xs) = null xs -- (pertenece x c) se verifica si x pertenece al conjunto c. Por ejemplo, -- c1 == {0,1,2,3,5,7,9} -- pertenece 3 c1 == True -- pertenece 4 c1 == False pertenece :: Ord a => a -> Conj a -> Bool pertenece x (Cj s) = x `elem` takeWhile (<= x) s -- (inserta x c) es el conjunto obtenido añadiendo el elemento x al -- conjunto c. Por ejemplo, -- c1 == {0,1,2,3,5,7,9} -- inserta 5 c1 == {0,1,2,3,5,7,9} -- inserta 4 c1 == {0,1,2,3,4,5,7,9} inserta :: Ord a => a -> Conj a -> Conj a inserta x (Cj s) = Cj (agrega x s) where agrega x [] = [x] agrega x s@(y:ys) | x > y = y : agrega x ys | x < y = x : s | otherwise = s -- (elimina x c) es el conjunto obtenido eliminando el elemento x -- del conjunto c. Por ejemplo, -- c1 == {0,1,2,3,5,7,9} -- elimina 3 c1 == {0,1,2,5,7,9} elimina :: Ord a => a -> Conj a -> Conj a elimina x (Cj s) = Cj (elimina x s) where elimina x [] = [] elimina x s@(y:ys) | x > y = y : elimina x ys | x < y = s | otherwise = ys -- --------------------------------------------------------------------- -- § Ejercicios -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 1. Definir la función -- subconjunto :: Ord a => Conj a -> Conj a -> Bool -- tal que (subconjunto c1 c2) se verifica si todos los elementos de c1 -- pertenecen a c2. Por ejemplo, -- subconjunto (Cj [2..100000]) (Cj [1..100000]) == True -- subconjunto (Cj [1..100000]) (Cj [2..100000]) == False -- --------------------------------------------------------------------- -- Se presentan distintas definiciones y se compara su eficiencia. -- 1ª definición subconjunto1 :: Ord a => Conj a -> Conj a -> Bool subconjunto1 (Cj xs) (Cj ys) = sublista xs ys where sublista [] _ = True sublista (x:xs) ys = elem x ys && sublista xs ys -- 2ª definición subconjunto2 :: Ord a => Conj a -> Conj a -> Bool subconjunto2 (Cj xs) c = and [pertenece x c | x <-xs] -- 3ª definición subconjunto3 :: Ord a => Conj a -> Conj a -> Bool subconjunto3 (Cj xs) (Cj ys) = sublista xs ys where sublista [] _ = True sublista _ [] = False sublista (x:xs) ys@(y:zs) = x >= y && elem x ys && sublista xs zs -- 4ª definición subconjunto4 :: Ord a => Conj a -> Conj a -> Bool subconjunto4 (Cj xs) (Cj ys) = sublista xs ys where sublista [] _ = True sublista _ [] = False sublista (x:xs) ys@(y:zs) | x < y = False | x == y = sublista xs zs | x > y = elem x zs && sublista xs zs -- Comparación de la eficiencia: -- ghci> subconjunto1 (Cj [2..100000]) (Cj [1..1000000]) -- C-c C-cInterrupted. -- ghci> subconjunto2 (Cj [2..100000]) (Cj [1..1000000]) -- C-c C-cInterrupted. -- ghci> subconjunto3 (Cj [2..100000]) (Cj [1..1000000]) -- True -- (0.52 secs, 26097076 bytes) -- ghci> subconjunto4 (Cj [2..100000]) (Cj [1..1000000]) -- True -- (0.66 secs, 32236700 bytes) -- ghci> subconjunto1 (Cj [2..100000]) (Cj [1..10000]) -- False -- (0.54 secs, 3679024 bytes) -- ghci> subconjunto2 (Cj [2..100000]) (Cj [1..10000]) -- False -- (38.19 secs, 1415562032 bytes) -- ghci> subconjunto3 (Cj [2..100000]) (Cj [1..10000]) -- False -- (0.08 secs, 3201112 bytes) -- ghci> subconjunto4 (Cj [2..100000]) (Cj [1..10000]) -- False -- (0.09 secs, 3708988 bytes) -- En lo que sigue, se usará la 3ª definición: subconjunto :: Ord a => Conj a -> Conj a -> Bool subconjunto = subconjunto3 -- --------------------------------------------------------------------- -- Ejercicio 2. Definir la función -- subconjuntoPropio :: Ord a => Conj a -> Conj a -> Bool -- tal (subconjuntoPropio c1 c2) se verifica si c1 es un subconjunto -- propio de c2. Por ejemplo, -- subconjuntoPropio (Cj [2..5]) (Cj [1..7]) == True -- subconjuntoPropio (Cj [2..5]) (Cj [1..4]) == False -- subconjuntoPropio (Cj [2..5]) (Cj [2..5]) == False -- --------------------------------------------------------------------- subconjuntoPropio :: Ord a => Conj a -> Conj a -> Bool subconjuntoPropio c1 c2 = subconjunto c1 c2 && c1 /= c2 -- --------------------------------------------------------------------- -- Ejercicio 3. Definir la función -- unitario :: Ord a => a -> Conj a -- tal que (unitario x) es el conjunto {x}. Por ejemplo, -- unitario 5 == {5} -- --------------------------------------------------------------------- unitario :: Ord a => a -> Conj a unitario x = inserta x vacio -- --------------------------------------------------------------------- -- Ejercicio 4. Definir la función -- cardinal :: Conj a -> Int -- tal que (cardinal c) es el número de elementos del conjunto c. Por -- ejemplo, -- cardinal c1 == 7 -- cardinal c2 == 5 -- --------------------------------------------------------------------- cardinal :: Conj a -> Int cardinal (Cj xs) = length xs -- --------------------------------------------------------------------- -- Ejercicio 5. Definir la función -- union :: Ord a => Conj a -> Conj a -> Conj a -- tal (union c1 c2) es la unión de ambos conjuntos. Por ejemplo, -- union c1 c2 == {0,1,2,3,5,6,7,8,9} -- cardinal (union2 c3 c4) == 100000 -- --------------------------------------------------------------------- -- Se considera distintas definiciones y se compara la eficiencia. -- 1ª definición: union1 :: Ord a => Conj a -> Conj a -> Conj a union1 (Cj xs) (Cj ys) = foldr inserta (Cj ys) xs -- Otra definión es union2 :: Ord a => Conj a -> Conj a -> Conj a union2 (Cj xs) (Cj ys) = Cj (unionL xs ys) where unionL [] ys = ys unionL xs [] = xs unionL l1@(x:xs) l2@(y:ys) | x < y = x : unionL xs l2 | x == y = x : unionL xs ys | x > y = y : unionL l1 ys -- Comparación de eficiencia -- ghci> :set +s -- ghci> let c = Cj [1..1000] -- ghci> cardinal (union1 c c) -- 1000 -- (1.04 secs, 56914332 bytes) -- ghci> cardinal (union2 c c) -- 1000 -- (0.01 secs, 549596 bytes) -- En lo que sigue se usará la 2ª definición union :: Ord a => Conj a -> Conj a -> Conj a union = union2 -- --------------------------------------------------------------------- -- Ejercicio 6. Definir la función -- unionG:: Ord a => [Conj a] -> Conj a -- tal (unionG cs) calcule la unión de la lista de conjuntos cd. Por -- ejemplo, -- unionG [c1, c2] == {0,1,2,3,5,6,7,8,9} -- --------------------------------------------------------------------- unionG:: Ord a => [Conj a] -> Conj a unionG [] = vacio unionG (Cj xs:css) = Cj xs `union` unionG css -- Se puede definir por plegados unionG2 :: Ord a => [Conj a] -> Conj a unionG2 = foldr union vacio -- --------------------------------------------------------------------- -- Ejercicio 7. Definir la función -- interseccion :: Eq a => Conj a -> Conj a -> Conj a -- tal que (interseccion c1 c2) es la intersección de los conjuntos c1 y -- c2. Por ejemplo, -- interseccion (Cj [1..7]) (Cj [4..9]) == {4,5,6,7} -- interseccion (Cj [2..1000000]) (Cj [1]) == {} -- --------------------------------------------------------------------- -- Se da distintas definiciones y se compara su eficiencia. -- 1ª definición interseccion1 :: Eq a => Conj a -> Conj a -> Conj a interseccion1 (Cj xs) (Cj ys) = Cj [x | x <- xs, x `elem` ys] -- 2ª definición interseccion2 :: Ord a => Conj a -> Conj a -> Conj a interseccion2 (Cj xs) (Cj ys) = Cj (interseccionL xs ys) where interseccionL l1@(x:xs) l2@(y:ys) | x > y = interseccionL l1 ys | x == y = x : interseccionL xs ys | x < y = interseccionL xs l2 interseccionL _ _ = [] -- La comparación de eficiencia es -- ghci> interseccion1 (Cj [2..1000000]) (Cj [1]) -- {} -- (0.32 secs, 80396188 bytes) -- ghci> interseccion2 (Cj [2..1000000]) (Cj [1]) -- {} -- (0.00 secs, 2108848 bytes) -- En lo que sigue se usa la 2ª definición: interseccion :: Ord a => Conj a -> Conj a -> Conj a interseccion = interseccion2 -- --------------------------------------------------------------------- -- Ejercicio 8. Definir la función -- interseccionG:: Ord a => [Conj a] -> Conj a -- tal que (interseccionG cs) es la intersección de la lista de -- conjuntos cs. Por ejemplo, -- interseccionG [c1, c2] == {1,2,9} -- --------------------------------------------------------------------- interseccionG:: Ord a => [Conj a] -> Conj a interseccionG [c] = c interseccionG (cs:css) = interseccion cs (interseccionG css) -- Se puede definir por plegado interseccionG2 :: Ord a => [Conj a] -> Conj a interseccionG2 = foldr1 interseccion -- --------------------------------------------------------------------- -- Ejercicio 9. Definir la función -- disjuntos :: Ord a => Conj a -> Conj a -> Bool -- tal que (disjuntos c1 c2) se verifica si los conjuntos c1 y c2 son -- disjuntos. Por ejemplo, -- disjuntos (Cj [2..5]) (Cj [6..9]) == True -- disjuntos (Cj [2..5]) (Cj [1..9]) == False -- --------------------------------------------------------------------- disjuntos :: Ord a => Conj a -> Conj a -> Bool disjuntos c1 c2 = esVacio (interseccion c1 c2) -- --------------------------------------------------------------------- -- Ejercicio 10. Definir la función -- diferencia :: Eq a => Conj a -> Conj a -> Conj a -- tal que (diferencia c1 c2) es el conjunto de los elementos de c1 que -- no son elementos de c2. Por ejemplo, -- diferencia c1 c2 == {0,3,5,7} -- diferencia c2 c1 == {6,8} -- --------------------------------------------------------------------- diferencia :: Eq a => Conj a -> Conj a -> Conj a diferencia (Cj xs) (Cj ys) = Cj zs where zs = [x | x <- xs, x `notElem` ys] -- --------------------------------------------------------------------- -- Ejercicio 11. Definir la función -- diferenciaSimetrica :: Ord a => Conj a -> Conj a -> Conj a -- tal que (diferenciaSimetrica c1 c2) es la diferencia simétrica de los -- conjuntos c1 y c2. Por ejemplo, -- diferenciaSimetrica c1 c2 == {0,3,5,6,7,8} -- diferenciaSimetrica c2 c1 == {0,3,5,6,7,8} -- --------------------------------------------------------------------- diferenciaSimetrica :: Ord a => Conj a -> Conj a -> Conj a diferenciaSimetrica c1 c2 = diferencia (union c1 c2) (interseccion c1 c2) -- --------------------------------------------------------------------- -- Ejercicio 12. Definir la función -- filtra :: (a -> Bool) -> Conj a -> Conj a -- tal (filtra p c) es el conjunto de elementos de c que verifican el -- predicado p. Por ejemplo, -- filtra even c1 == {0,2} -- filtra odd c1 == {1,3,5,7,9} -- --------------------------------------------------------------------- filtra :: (a -> Bool) -> Conj a -> Conj a filtra p (Cj xs) = Cj (filter p xs) -- --------------------------------------------------------------------- -- Ejercicio 13. Definir la función -- particion :: (a -> Bool) -> Conj a -> (Conj a, Conj a) -- tal que (particion c) es el par formado por dos conjuntos: el de sus -- elementos que verifican p y el de los elementos que no lo -- verifica. Por ejemplo, -- particion even c1 == ({0,2},{1,3,5,7,9}) -- --------------------------------------------------------------------- particion :: (a -> Bool) -> Conj a -> (Conj a, Conj a) particion p c = (filtra p c, filtra (not . p) c) -- --------------------------------------------------------------------- -- Ejercicio 14. Definir la función -- divide :: (Ord a) => a-> Conj a -> (Conj a, Conj a) -- tal que (divide x c) es el par formado por dos subconjuntos de c: el -- de los elementos menores o iguales que x y el de los mayores que x. -- Por ejemplo, -- divide 5 c1 == ({0,1,2,3,5},{7,9}) -- --------------------------------------------------------------------- divide :: Ord a => a-> Conj a -> (Conj a, Conj a) divide x = particion (<= x) -- --------------------------------------------------------------------- -- Ejercicio 15. Definir la función -- mapC :: (a -> b) -> Conj a -> Conj b -- tal que (map f c) es el conjunto formado por las imágenes de los -- elemsntos de c, mediante f. Por ejemplo, -- mapC (*2) (Cj [1..4]) == {2,4,6,8} -- --------------------------------------------------------------------- mapC :: (a -> b) -> Conj a -> Conj b mapC f (Cj xs) = Cj (map f xs) -- --------------------------------------------------------------------- -- Ejercicio 16. Definir la función -- everyC :: (a -> Bool) -> Conj a -> Bool -- tal que (everyC p c) se verifica si todos los elemsntos de c -- verifican el predicado p. Por ejmplo, -- everyC even (Cj [2,4..10]) == True -- everyC even (Cj [2..10]) == False -- --------------------------------------------------------------------- everyC :: (a -> Bool) -> Conj a -> Bool everyC p (Cj xs) = all p xs -- --------------------------------------------------------------------- -- Ejercicio 17. Definir la función -- someC :: (a -> Bool) -> Conj a -> Bool -- tal que (someC p c) se verifica si algún elemento de c verifica el -- predicado p. Por ejemplo, -- someC even (Cj [1,4,7]) == True -- someC even (Cj [1,3,7]) == False -- --------------------------------------------------------------------- someC :: (a -> Bool) -> Conj a -> Bool someC p (Cj xs) = any p xs -- --------------------------------------------------------------------- -- Ejercicio 18. Definir la función -- productoC :: (Ord a, Ord b) => Conj a -> Conj b -> Conj (a,b) -- tal que (productoC c1 c2) es el producto cartesiano de los -- conjuntos c1 y c2. Por ejemplo, -- productoC (Cj [1,3]) (Cj [2,4])== {(1,2),(1,4),(3,2),(3,4)} -- --------------------------------------------------------------------- productoC :: (Ord a, Ord b) => Conj a -> Conj b -> Conj (a,b) productoC (Cj xs) (Cj ys) = foldr inserta vacio [(x,y) | x <- xs, y <- ys] -- --------------------------------------------------------------------- -- Ejercicio. Especificar que, dado un tipo ordenado a, el orden entre -- los conjuntos con elementos en a es el orden inducido por el orden -- existente entre las listas con elementos en a. -- --------------------------------------------------------------------- instance Ord a => Ord (Conj a) where (Cj xs) <= (Cj ys) = xs <= ys -- --------------------------------------------------------------------- -- Ejercicio 19. Definir la función -- potencia :: Ord a => Conj a -> Conj (Conj a) -- tal que (potencia c) es el conjunto potencia de c; es decir, el -- conjunto de todos los subconjuntos de c. Por ejemplo, -- potencia (Cj [1,2]) == {{},{1},{1,2},{2}} -- potencia (Cj [1..3]) == {{},{1},{1,2},{1,2,3},{1,3},{2},{2,3},{3}} -- --------------------------------------------------------------------- potencia :: Ord a => Conj a -> Conj (Conj a) potencia (Cj []) = unitario vacio potencia (Cj (x:xs)) = mapC (inserta x) pr `union` pr where pr = potencia (Cj xs) -- --------------------------------------------------------------------- -- Ejercicio 20. Comprobar con QuickCheck que la relación de subconjunto -- es un orden parcial. Es decir, es una relación reflexiva, -- antisimétrica y transitiva. -- --------------------------------------------------------------------- propSubconjuntoReflexiva:: Conj Int -> Bool propSubconjuntoReflexiva c = subconjunto c c -- La comprobación es -- ghci> quickCheck propSubconjuntoReflexiva -- +++ OK, passed 100 tests. propSubconjuntoAntisimetrica:: Conj Int -> Conj Int -> Property propSubconjuntoAntisimetrica c1 c2 = subconjunto c1 c2 && subconjunto c2 c1 ==> c1 == c2 -- La comprobación es -- ghci> quickCheck propSubconjuntoAntisimetrica -- *** Gave up! Passed only 13 tests. propSubconjuntoTransitiva :: Conj Int -> Conj Int -> Conj Int -> Property propSubconjuntoTransitiva c1 c2 c3 = subconjunto c1 c2 && subconjunto c2 c3 ==> subconjunto c1 c3 -- La comprobación es -- ghci> quickCheck propSubconjuntoTransitiva -- *** Gave up! Passed only 7 tests. -- --------------------------------------------------------------------- -- Ejercicio 21. Comprobar con QuickCheck que el conjunto vacío está -- contenido en cualquier conjunto. -- --------------------------------------------------------------------- propSubconjuntoVacio:: Conj Int -> Bool propSubconjuntoVacio c = subconjunto vacio c -- La comprobación es -- ghci> quickCheck propSubconjuntoVacio -- +++ OK, passed 100 tests. -- --------------------------------------------------------------------- -- Ejercicio 22. Comprobar con QuickCheck las siguientes propiedades de -- la unión de conjuntos: -- Idempotente: A U A = A -- Neutro: A U {} = A -- Commutativa: A U B = B U A -- Asociativa: A U (B U C) = (A U B) U C -- UnionSubconjunto: A y B son subconjuntos de (A U B) -- UnionDiferencia: A U B = A U (B \ A) -- --------------------------------------------------------------------- propUnionIdempotente :: Conj Int -> Bool propUnionIdempotente c = union c c == c -- La comprobación es -- ghci> quickCheck propUnionIdempotente -- +++ OK, passed 100 tests. propVacioNeutroUnion:: Conj Int -> Bool propVacioNeutroUnion c = union c vacio == c -- La comprobación es -- ghci> quickCheck propVacioNeutroUnion -- +++ OK, passed 100 tests. propUnionCommutativa:: Conj Int -> Conj Int -> Bool propUnionCommutativa c1 c2 = union c1 c2 == union c2 c1 -- La comprobación es -- ghci> quickCheck propUnionCommutativa -- +++ OK, passed 100 tests. propUnionAsociativa:: Conj Int -> Conj Int -> Conj Int -> Bool propUnionAsociativa c1 c2 c3 = union c1 (union c2 c3) == union (union c1 c2) c3 -- La comprobación es -- ghci> quickCheck propUnionAsociativa -- +++ OK, passed 100 tests. propUnionSubconjunto :: Conj Int -> Conj Int -> Bool propUnionSubconjunto c1 c2 = subconjunto c1 c3 && subconjunto c2 c3 where c3 = union c1 c2 -- La comprobación es -- ghci> quickCheck propUnionSubconjunto -- +++ OK, passed 100 tests. propUnionDiferencia :: Conj Int -> Conj Int -> Bool propUnionDiferencia c1 c2 = union c1 c2 == union c1 (diferencia c2 c1) -- La comprobación es -- ghci> quickCheck propUnionDiferencia -- +++ OK, passed 100 tests. -- --------------------------------------------------------------------- -- Ejercicio 23. Comprobar con QuickCheck las siguientes propiedades de -- la intersección de conjuntos: -- Idempotente: A n A = A -- VacioInterseccion: A n {} = {} -- Commutativa: A n B = B n A -- Asociativa: A n (B n C) = (A n B) n C -- InterseccionSubconjunto: (A n B) es subconjunto de A y B -- DistributivaIU: A n (B U C) = (A n B) U (A n C) -- DistributivaUI: A U (B n C) = (A U B) n (A U C) -- --------------------------------------------------------------------- propInterseccionIdempotente :: Conj Int -> Bool propInterseccionIdempotente c = interseccion c c == c -- La comprobación es -- ghci> quickCheck propInterseccionIdempotente -- +++ OK, passed 100 tests. propVacioInterseccion:: Conj Int -> Bool propVacioInterseccion c = interseccion c vacio == vacio -- La comprobación es -- ghci> quickCheck propVacioInterseccion -- +++ OK, passed 100 tests. propInterseccionCommutativa:: Conj Int -> Conj Int -> Bool propInterseccionCommutativa c1 c2 = interseccion c1 c2 == interseccion c2 c1 -- La comprobación es -- ghci> quickCheck propInterseccionCommutativa -- +++ OK, passed 100 tests. propInterseccionAsociativa:: Conj Int -> Conj Int -> Conj Int -> Bool propInterseccionAsociativa c1 c2 c3 = interseccion c1 (interseccion c2 c3) == interseccion (interseccion c1 c2) c3 -- La comprobación es -- ghci> quickCheck propInterseccionAsociativa -- +++ OK, passed 100 tests. propInterseccionSubconjunto :: Conj Int -> Conj Int -> Bool propInterseccionSubconjunto c1 c2 = subconjunto c3 c1 && subconjunto c3 c2 where c3 = interseccion c1 c2 -- La comprobación es -- ghci> quickCheck propInterseccionSubconjunto -- +++ OK, passed 100 tests. propDistributivaIU:: Conj Int -> Conj Int -> Conj Int -> Bool propDistributivaIU c1 c2 c3 = interseccion c1 (union c2 c3) == union (interseccion c1 c2) (interseccion c1 c3) -- La comprobación es -- ghci> quickCheck propDistributivaIU -- +++ OK, passed 100 tests. propDistributivaUI:: Conj Int -> Conj Int -> Conj Int -> Bool propDistributivaUI c1 c2 c3 = union c1 (interseccion c2 c3) == interseccion (union c1 c2) (union c1 c3) -- La comprobación es -- ghci> quickCheck propDistributivaUI -- +++ OK, passed 100 tests. -- --------------------------------------------------------------------- -- Ejercicio 24. Comprobar con QuickCheck las siguientes propiedades de -- la diferencia de conjuntos: -- DiferenciaVacio1: A \ {} = A -- DiferenciaVacio2: {} \ A = {} -- DiferenciaDif1: (A \ B) \ C = A \ (B U C) -- DiferenciaDif2: A \ (B \ C) = (A \ B) U (A n C) -- DiferenciaSubc: (A \ B) es subconjunto de A -- DiferenciaDisj: A y (B \ A) son disjuntos -- DiferenciaUI: (A U B) \ A = B \ (A n B) -- --------------------------------------------------------------------- propDiferenciaVacio1 :: Conj Int -> Bool propDiferenciaVacio1 c = diferencia c vacio == c -- La comprobación es -- ghci> quickCheck propDiferenciaVacio2 -- +++ OK, passed 100 tests. propDiferenciaVacio2 :: Conj Int -> Bool propDiferenciaVacio2 c = diferencia vacio c == vacio -- La comprobación es -- ghci> quickCheck propDiferenciaVacio2 -- +++ OK, passed 100 tests. propDiferenciaDif1 :: Conj Int -> Conj Int -> Conj Int -> Bool propDiferenciaDif1 c1 c2 c3 = diferencia (diferencia c1 c2) c3 == diferencia c1 (union c2 c3) -- La comprobación es -- ghci> quickCheck propDiferenciaDif1 -- +++ OK, passed 100 tests. propDiferenciaDif2 :: Conj Int -> Conj Int -> Conj Int -> Bool propDiferenciaDif2 c1 c2 c3 = diferencia c1 (diferencia c2 c3) == union (diferencia c1 c2) (interseccion c1 c3) -- La comprobación es -- ghci> quickCheck propDiferenciaDif2 -- +++ OK, passed 100 tests. propDiferenciaSubc:: Conj Int -> Conj Int -> Bool propDiferenciaSubc c1 c2 = subconjunto (diferencia c1 c2) c1 -- La comprobación es -- ghci> quickCheck propDiferenciaSubc -- +++ OK, passed 100 tests. propDiferenciaDisj:: Conj Int -> Conj Int -> Bool propDiferenciaDisj c1 c2 = disjuntos c1 (diferencia c2 c1) -- La comprobación es -- ghci> quickCheck propDiferenciaDisj -- +++ OK, passed 100 tests. propDiferenciaUI:: Conj Int -> Conj Int -> Bool propDiferenciaUI c1 c2 = diferencia (union c1 c2) c1 == diferencia c2 (interseccion c1 c2) -- La comprobación es -- ghci> quickCheck propDiferenciaUI -- +++ OK, passed 100 tests. -- --------------------------------------------------------------------- -- Generador de conjuntos -- -- --------------------------------------------------------------------- -- genConjunto es un generador de conjuntos. Por ejemplo, -- ghci> sample genConjunto -- {} -- {} -- {} -- {3,-2,-2,-3,-2,4} -- {-8,0,4,6,-5,-2} -- {12,-2,-1,-10,-2,2,15,15} -- {2} -- {} -- {-42,55,55,-11,23,23,-11,27,-17,-48,16,-15,-7,5,41,43} -- {-124,-66,-5,-47,58,-88,-32,-125} -- {49,-38,-231,-117,-32,-3,45,227,-41,54,169,-160,19} genConjunto :: Gen (Conj Int) genConjunto = do xs <- listOf arbitrary return (foldr inserta vacio xs) -- Los conjuntos son concreciones de los arbitrarios. instance Arbitrary (Conj Int) where arbitrary = genConjunto |