Reparto de escaños por la ley d’Hont
El sistema D’Hondt es una fórmula creada por Victor d’Hondt, que permite obtener el número de cargos electos asignados a las candidaturas, en proporción a los votos conseguidos.
Tras el recuento de los votos, se calcula una serie de divisores para cada partido. La fórmula de los divisores es V/N, donde V representa el número total de votos recibidos por el partido, y N representa cada uno de los números enteros desde 1 hasta el número de cargos electos de la circunscripción objeto de escrutinio. Una vez realizadas las divisiones de los votos de cada partido por cada uno de los divisores desde 1 hasta N, la asignación de cargos electos se hace ordenando los cocientes de las divisiones de mayor a menor y asignando a cada uno un escaño hasta que éstos se agoten
Definir la función
1 |
reparto :: Int -> [Int] -> [(Int,Int)] |
tal que (reparto n vs) es la lista de los pares formados por los números de los partidos y el número de escaño que les corresponden al repartir n escaños en función de la lista de sus votos. Por ejemplo,
1 2 3 4 |
ghci> reparto 7 [340000,280000,160000,60000,15000] [(1,3),(2,3),(3,1)] ghci> reparto 21 [391000,311000,184000,73000,27000,12000,2000] [(1,9),(2,7),(3,4),(4,1)] |
es decir, en el primer ejemplo,
- al 1º partido (que obtuvo 340000 votos) le corresponden 3 escaños,
- al 2º partido (que obtuvo 280000 votos) le corresponden 3 escaños,
- al 3º partido (que obtuvo 160000 votos) le corresponden 1 escaño.
Soluciones
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 |
import Data.List (sort, group) -- Para los ejemplos que siguen, se usará la siguiente ditribución de -- votos entre 5 partidos. ejVotos :: [Int] ejVotos = [340000,280000,160000,60000,15000] -- 1ª solución -- =========== reparto :: Int -> [Int] -> [(Int,Int)] reparto n vs = [(x,1 + length xs) | (x:xs) <- group (sort (repartoAux n vs))] -- (repartoAux n vs) es el número de los partidos, cuyos votos son vs, que -- obtienen los n escaños. Por ejemplo, -- ghci> repartoAux 7 ejVotos -- [1,2,1,3,2,1,2] repartoAux :: Int -> [Int] -> [Int] repartoAux n vs = map snd (repartoAux' n vs) -- (repartoAux' n vs) es la lista formada por los n restos mayores -- correspondientes a la lista de votos vs. Por ejemplo, -- ghci> repartoAux' 7 ejVotos -- [(340000,1),(280000,2),(170000,1),(160000,3),(140000,2),(113333,1), -- (93333,2)] repartoAux' :: Int -> [Int] -> [(Int,Int)] repartoAux' n vs = take n (reverse (sort (concatMap (restos n) (votosPartidos vs)))) -- (votosPartidos vs) es la lista con los pares formados por los votos y -- el número de cada partido. Por ejemplo, -- ghci> votosPartidos ejVotos -- [(340000,1),(280000,2),(160000,3),(60000,4),(15000,5)] votosPartidos :: [Int] -> [(Int,Int)] votosPartidos vs = zip vs [1..] -- (restos n (x,i)) es la lista obtenidas dividiendo n entre 1, 2,..., n. -- Por ejemplo, -- ghci> restos 5 (340000,1) -- [(340000,1),(170000,1),(113333,1),(85000,1),(68000,1)] restos :: Int -> (Int,Int) -> [(Int,Int)] restos n (x,i) = [(x `div` k,i) | k <- [1..n]] -- 2ª solución -- =========== reparto2 :: Int -> [Int] -> [(Int,Int)] reparto2 n xs = ( map (\x -> (head x, length x)) . group . sort . map snd . take n . reverse . sort ) [(x `div` i, p) | (x,p) <- zip xs [1..], i <- [1..n]] |
Otras soluciones
- Se pueden escribir otras soluciones en los comentarios.
- El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>
3 Comentarios