-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNumeros_de_ocurrencias_de_elementos.hs
134 lines (109 loc) · 4.26 KB
/
Numeros_de_ocurrencias_de_elementos.hs
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
-- Numeros_de_ocurrencias_de_elementos.hs
-- Número de ocurrencias de elementos.
-- José A. Alonso Jiménez
-- Sevilla, 7-febrero-2022
-- ---------------------------------------------------------------------
-- ---------------------------------------------------------------------
-- Definir la función
-- ocurrenciasElementos :: Ord a => [a] -> [(a,Int)]
-- tal que (ocurrencias xs) es el conjunto de los elementos de xs junto
-- con sus números de ocurrencias. Por ejemplo,
-- ocurrenciasElementos1 [3,2,3,1,2,3,5,3] == [(3,4),(2,2),(1,1),(5,1)]
-- ocurrenciasElementos1 "tictac" == [('t',2),('i',1),('c',2),('a',1)]
-- ---------------------------------------------------------------------
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
module Numeros_de_ocurrencias_de_elementos where
import Data.List (group, nub, sort)
import Data.Maybe (fromJust)
import qualified Data.Map as M
import Test.Hspec (Spec, describe, hspec, it, shouldBe)
import Test.QuickCheck
-- 1ª solución
-- ===========
ocurrenciasElementos1 :: Ord a => [a] -> [(a,Int)]
ocurrenciasElementos1 xs =
[(x,ocurrencias x xs) | x <- nub xs]
-- (ocurrencias x xs) es el número de ocurrencias de x en xs. Por
-- ejemplo,
-- ocurrencias 'a' "Salamanca" == 4
ocurrencias :: Ord a => a -> [a] -> Int
ocurrencias x xs = length (filter (==x) xs)
-- 2ª solución
-- ===========
ocurrenciasElementos2 :: Ord a => [a] -> [(a,Int)]
ocurrenciasElementos2 xs = map ocurrencias2 (nub xs)
where ocurrencias2 x = (x,fromJust (lookup x (frecuencias xs)))
-- (frecuencias xs) es la lista ordenada de los elementos de xs juntos
-- con sus números de ocurrencias. Por ejemplo,
-- frecuencias [3,2,3,1,2,3,5,3] == [(1,1),(2,2),(3,4),(5,1)]
frecuencias :: Ord a => [a] -> [(a, Int)]
frecuencias xs = [(head ys, length ys) | ys <- group (sort xs)]
-- 3ª solución
-- ===========
ocurrenciasElementos3 :: Ord a => [a] -> [(a,Int)]
ocurrenciasElementos3 xs = map ocurrencias3 (nub xs)
where diccionario = dicFrecuencias xs
ocurrencias3 x = (x, diccionario M.! x)
-- (dicFrecuencias xs) es el diccionario de los elementos de xs juntos
-- con sus números de ocurrencias. Por ejemplo,
-- λ> dicFrecuencias [3,2,3,1,2,3,5,3]
-- fromList [(1,1),(2,2),(3,4),(5,1)]
dicFrecuencias :: Ord a => [a] -> M.Map a Int
dicFrecuencias xs = M.fromListWith (+) (zip xs (repeat 1))
-- 4ª solución
-- ===========
ocurrenciasElementos4 :: Ord a => [a] -> [(a,Int)]
ocurrenciasElementos4 = foldl aux []
where
aux [] y = [(y,1)]
aux ((x,k):xs) y | x == y = (x, k + 1) : xs
| otherwise = (x, k) : aux xs y
-- Verificación
-- ============
verifica :: IO ()
verifica = hspec spec
specG :: (String -> [(Char,Int)]) -> Spec
specG ocurrenciasElementos = do
it "e1" $
ocurrenciasElementos "abracadabra" `shouldBe`
[('a',5),('b',2),('r',2),('c',1),('d',1)]
it "e2" $
ocurrenciasElementos "Code Wars" `shouldBe`
[('C',1),('o',1),('d',1),('e',1),(' ',1),('W',1),('a',1),('r',1),('s',1)]
spec :: Spec
spec = do
describe "def. 1" $ specG ocurrenciasElementos1
describe "def. 2" $ specG ocurrenciasElementos2
describe "def. 3" $ specG ocurrenciasElementos3
describe "def. 4" $ specG ocurrenciasElementos4
-- La verificación es
-- λ> verifica
--
-- 4 examples, 0 failures
-- Comprobación de equivalencia
-- ============================
-- La propiedad es
prop_ocurrenciasElementos :: [Integer] -> Bool
prop_ocurrenciasElementos xs =
all (== ocurrenciasElementos1 xs)
[f xs | f <- [ocurrenciasElementos2,
ocurrenciasElementos3,
ocurrenciasElementos4]]
-- La comprobación es
-- λ> quickCheck prop_ocurrenciasElementos
-- +++ OK, passed 100 tests.
-- Comparación de eficiencia
-- =========================
-- La comparación es
-- λ> last (ocurrenciasElementos1 (show (product [1..10^5])))
-- ('5',42935)
-- (7.93 secs, 11,325,169,512 bytes)
-- λ> last (ocurrenciasElementos2 (show (product [1..10^5])))
-- ('5',42935)
-- (8.46 secs, 11,750,911,592 bytes)
-- λ> last (ocurrenciasElementos3 (show (product [1..10^5])))
-- ('5',42935)
-- (8.29 secs, 11,447,015,896 bytes)
-- λ> last (ocurrenciasElementos4 (show (product [1..10^5])))
-- ('5',42935)
-- (9.97 secs, 12,129,527,912 bytes)