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]] |
Pensamiento
Sus cantares llevan
agua de remanso,
que parece quieta.
Y que no lo está;
mas no tiene prisa
por ir a la mar.Antonio Machado
En el siguiente ejemplo falla
ya que asigna 277 escaños en lugar de 100.
Ya ha sido solucionado. Ahora si reparte el número de escaños correcto
Como la primera respuesta falla. Por ejemplo,
ya que asigna 301 escaños en lugar de 100.
La prueba de la eficacia se deja como prueba al lector