Código de las alergias
Para la determinación de las alergia se utiliza los siguientes códigos para los alérgenos:
1 2 3 4 5 6 7 8 |
Huevos ........ 1 Cacahuetes .... 2 Mariscos ...... 4 Fresas ........ 8 Tomates ....... 16 Chocolate ..... 32 Polen ......... 64 Gatos ......... 128 |
Así, si Juan es alérgico a los cacahuetes y al chocolate, su puntuación es 34 (es decir, 2+32).
Los alérgenos se representan mediante el siguiente tipo de dato
1 2 3 4 5 6 7 8 9 |
data Alergeno = Huevos | Cacahuetes | Mariscos | Fresas | Tomates | Chocolate | Polen | Gatos deriving (Enum, Eq, Show, Bounded) |
Definir la función
1 |
alergias :: Int -> [Alergeno] |
tal que (alergias n) es la lista de alergias correspondiente a una puntuación n. Por ejemplo,
1 2 3 4 5 6 7 8 9 10 |
λ> alergias 1 [Huevos] λ> alergias 2 [Cacahuetes] λ> alergias 3 [Huevos,Cacahuetes] λ> alergias 5 [Huevos,Mariscos] λ> alergias 255 [Huevos,Cacahuetes,Mariscos,Fresas,Tomates,Chocolate,Polen,Gatos] |
Soluciones
[schedule expon=’2022-04-18′ expat=»06:00″]
- Las soluciones se pueden escribir en los comentarios.
- El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>
[/schedule]
[schedule on=’2022-04-18′ at=»06:00″]
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 |
import Data.List (subsequences) import Test.QuickCheck data Alergeno = Huevos | Cacahuetes | Mariscos | Fresas | Tomates | Chocolate | Polen | Gatos deriving (Enum, Eq, Show, Bounded) -- 1ª solución -- =========== alergias1 :: Int -> [Alergeno] alergias1 n = [a | (a,c) <- zip alergenos codigos, c `elem` descomposicion n] -- codigos es la lista de los códigos de los alergenos. codigos :: [Int] codigos = [2^x| x <- [0..7]] -- (descomposicion n) es la descomposición de n como sumas de potencias -- de 2. Por ejemplo, -- descomposicion 3 == [1,2] -- descomposicion 5 == [1,4] -- descomposicion 248 == [8,16,32,64,128] -- descomposicion 255 == [1,2,4,8,16,32,64,128] descomposicion :: Int -> [Int] descomposicion n = head [xs | xs <- subsequences codigos, sum xs == n] -- 2ª solución -- =========== alergias2 :: Int -> [Alergeno] alergias2 = map toEnum . codigosAlergias -- (codigosAlergias n) es la lista de códigos de alergias -- correspondiente a una puntuación n. Por ejemplo, -- codigosAlergias 1 == [0] -- codigosAlergias 2 == [1] -- codigosAlergias 3 == [0,1] -- codigosAlergias 4 == [2] -- codigosAlergias 5 == [0,2] -- codigosAlergias 6 == [1,2] codigosAlergias :: Int -> [Int] codigosAlergias = aux [0..7] where aux [] _ = [] aux (x:xs) n | odd n = x : aux xs (n `div` 2) | otherwise = aux xs (n `div` 2) -- 3ª solución -- =========== alergias3 :: Int -> [Alergeno] alergias3 = map toEnum . codigosAlergias3 codigosAlergias3 :: Int -> [Int] codigosAlergias3 n = [x | (x,y) <- zip [0..7] (int2bin n), y == 1] -- (int2bin n) es la representación binaria del número n. Por ejemplo, -- int2bin 10 == [0,1,0,1] -- ya que 10 = 0*1 + 1*2 + 0*4 + 1*8 int2bin :: Int -> [Int] int2bin n | n < 2 = [n] | otherwise = n `rem` 2 : int2bin (n `div` 2) -- 4ª solución -- =========== alergias4 :: Int -> [Alergeno] alergias4 = map toEnum . codigosAlergias4 codigosAlergias4 :: Int -> [Int] codigosAlergias4 n = map fst (filter ((== 1) . snd) (zip [0..7] (int2bin n))) -- 5ª solución -- =========== alergias5 :: Int -> [Alergeno] alergias5 = map (toEnum . fst) . filter ((1 ==) . snd) . zip [0..7] . int2bin -- 6ª solución -- =========== alergias6 :: Int -> [Alergeno] alergias6 = aux alergenos where aux [] _ = [] aux (x:xs) n | odd n = x : aux xs (n `div` 2) | otherwise = aux xs (n `div` 2) -- alergenos es la lista de los alergenos. Por ejemplo. -- take 3 alergenos == [Huevos,Cacahuetes,Mariscos] alergenos :: [Alergeno] alergenos = [minBound..maxBound] -- Comprobación de equivalencia -- ============================ -- La propiedad es prop_alergias :: Property prop_alergias = forAll (arbitrary `suchThat` esValido) $ \n -> all (== alergias1 n) [alergias2 n, alergias3 n, alergias4 n, alergias5 n, alergias6 n] where esValido x = 1 <= x && x <= 255 -- La comprobación es -- λ> quickCheck prop_alergias -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> last (map alergias1 [1..255]) -- [Huevos,Cacahuetes,Mariscos,Fresas,Tomates,Chocolate,Polen,Gatos] -- (0.02 secs, 1,657,912 bytes) -- λ> last (map alergias2 [1..255]) -- [Huevos,Cacahuetes,Mariscos,Fresas,Tomates,Chocolate,Polen,Gatos] -- (0.01 secs, 597,080 bytes) -- λ> last (map alergias3 [1..255]) -- [Huevos,Cacahuetes,Mariscos,Fresas,Tomates,Chocolate,Polen,Gatos] -- (0.01 secs, 597,640 bytes) -- λ> last (map alergias4 [1..255]) -- [Huevos,Cacahuetes,Mariscos,Fresas,Tomates,Chocolate,Polen,Gatos] -- (0.01 secs, 598,152 bytes) -- λ> last (map alergias5 [1..255]) -- [Huevos,Cacahuetes,Mariscos,Fresas,Tomates,Chocolate,Polen,Gatos] -- (0.01 secs, 596,888 bytes) |
El código se encuentra en [GitHub](https://github.com/jaalonso/Exercitium/blob/main/src/Alergias.hs).
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>
[/schedule]