De United States Census1 is een volkstelling die om de tien jaar georganiseerd wordt in de Verenigde Staten. Deze telling wordt uitgevoerd door het Bureau of the Census2 en is geregeld in de Amerikaanse grondwet. De resultaten van deze telling worden onder andere gebruikt om de 435 stemgerechtigde leden van het Huis van Afgevaardigden3 (House of Representatives) toe te wijzen aan de 50 staten. Sinds 1940 gebeurt deze toewijzing aan de hand van een methode die werd ontwikkeld door Edward Vermilye Huntington4 en Joseph Adna Hill5.
De Huntington-Hill methode6 begint met aan elke staat één vertegenwoordiger toe te kennen. Daarna worden de overige vertegenwoordigers één voor één aan een staat toegekend, door in elke ronde de volgende waarde te berekenen voor elke staat: \[g(n, p) = \frac{p}{\sqrt{n(n+1)}}\] Hierbij komt $$n$$ overeen met het huidig aantal vertegenwoordigers toegekend aan de staat (initieel 1) en $$p$$ met het bevolkingsaantal van de staat. De waarde $$g(n, p)$$ is dus het bevolkingsaantal van de staat gedeeld door het geometrisch gemiddelde7 van het huidig aantal vertegenwoordigers en het aantal vertegenwoordigers dat de staat zou hebben als het de volgende vertegenwoordiger zou toegewezen krijgen. Het geometrisch gemiddelde $$g(n, p)$$ wordt voor elke staat in elke ronde opnieuw berekend, en de volgende vertegenwoordiger wordt toegewezen aan de staat met het grootste geometrisch gemiddelde $$g(n, p)$$.
Als bijvoorbeeld aan elke staat initieel één vertegenwoordiger werd toegewezen, dan is het geometrisch gemiddelde van elke staat gelijk aan het bevolkingsaantal van de staat gedeeld door de vierkantswortel van 2. Aangezien Californië het grootste bevolkingsaantal heeft, krijgt het de 51ste vertegenwoordiger toegewezen. Daarna wordt het geometrisch gemiddelde $$g(n, p)$$ van Californië herberekend door het bevolkingsaantal te delen door de vierkantswortel van $$2 \times 3 = 6$$, en in de tweede ronde wordt de 52ste vertegenwoordiger toegewezen aan Texas, dat het tweede grootste bevolkingsaantal en nu dus ook het grootste geometrisch gemiddelde $$g(n, p)$$ heeft. Dit gaat zo $$435 - 50 = 385$$ ronden verder, totdat alle vertegenwoordigers werden toegewezen.
We werken met kommagescheiden bestanden8 (CSV-bestanden; comma-separated values) die de resultaten van één of meer volkstellingen bevatten. De eerste kolom bevat de namen van de regio's (bv. de staten van de Verenigde Staten) waarvan de bevolkingsaantallen gerapporteerd worden. Elke overige kolom bevat de bevolkingsaantallen per regio voor een volkstelling in het jaar dat als hoofding van de kolom gebruikt wordt. Als voorbeeld tonen we hieronder de eerste regels van zo een CSV-bestand:
REGION,1910,1920,1930,1940,1950,1960,1970,1980,1990,2000,2010 Alabama,2138093,2348174,2646248,2832961,3061743,3266740,3444165,3893888,4040587,4447100,4779736 Alaska,64356,55036,59278,72524,128643,226167,300382,401851,550043,626932,710231 Arizona,204354,334162,435573,499261,749587,1302161,1770900,2718215,3665228,5130632,6392017 Arkansas,1574449,1752204,1854482,1949387,1909511,1786272,1923295,2286435,2350725,2673400,2915918 California,2377549,3426861,5677251,6907387,10586223,15717204,19953134,23667902,29760021,33871648,37253956 Colorado,799024,939629,1035791,1123296,1325089,1753947,2207259,2889964,3294394,4301261,5029196 Connecticut,1114756,1380631,1606903,1709242,2007280,2535234,3031709,3107576,3287116,3405565,3574097 Delaware,202322,223003,238380,266505,318085,446292,548104,594338,666168,783600,897934 Florida,752619,968470,1468211,1897414,2771305,4951560,6789443,9746324,12937926,15982378,18801310 …
Gevraagd wordt:
Schrijf een functie inwoners waaraan twee argumenten moeten doorgegeven worden: i) een jaartal (int) en ii) de locatie (str) van een CSV-bestand dat de resultaten van één of meer volkstellingen bevat. Als het CSV-bestand geen kolom bevat die overeenkomt met het gegeven jaartal, dan moet een AssertionError opgeworpen worden met de boodschap geen gegevens beschikbaar. Anders moet de functie een dictionary (dict) teruggeven waarvan de sleutels gevormd worden door de namen (str) van alle regio's uit het gegeven CSV-bestand. Elk van deze sleutels moet afgebeeld worden op het bevolkingsaantal (int) voor die regio uit de kolom van het gegeven CSV-bestand die overeenkomt met het gegeven jaartal.
Schrijf een functie verdeling waaraan twee argumenten moeten doorgegeven worden: i) een dictionary (dict) die namen (str) van regio's afbeeldt op hun bevolkingsaantal (int) cfr. de dictionaries die door de functie inwoners teruggegeven worden en ii) een aantal te verdelen vertegenwoordigers (int). Als het gegeven aantal vertegenwoordigers kleiner is dan het aantal regio's in de gegeven dictionary, dan moet een AssertionError opgeworpen worden met de boodschap te weinig vertegenwoordigers. Anders moet de functie een dictionary (dict) teruggeven die dezelfde sleutels gebruikt als de gegeven dictionary. Elk van deze sleutels moet door de dictionary afgebeeld worden op het aantal vertegenwoordigers (int) dat aan deze regio wordt toegewezen volgens de Huntington-Hill methode, gebruikmakend van de bevolkingsaantallen uit de gegeven dictionary.
Bij onderstaande voorbeeldsessie gaan we ervan uit dat het CSV-bestand vs_bevolkingsaantal.csv9 zich in de huidige directory bevindt.
>>> vs2010 = inwoners(2010, 'vs_bevolkingsaantal.csv10')
>>> vs2010['Alabama']
4779736
>>> vs2010['Hawaii']
1360301
>>> vs2010['Wyoming']
563626
>>> verdeling(vs2010, 435)
{'Oklahoma': 5, 'Illinois': 18, 'Pennsylvania': 18, 'Iowa': 4, 'Maine': 2, 'South Dakota': 1, 'Nebraska': 3, 'New Jersey': 12, 'Maryland': 8, 'Texas': 36, 'Alabama': 7, 'Idaho': 2, 'South Carolina': 7, 'Michigan': 14, 'Tennessee': 9, 'Kansas': 4, 'Wyoming': 1, 'Wisconsin': 8, 'Louisiana': 6, 'Nevada': 4, 'Vermont': 1, 'Massachusetts': 9, 'Kentucky': 6, 'California': 53, 'Missouri': 8, 'Colorado': 7, 'Arizona': 9, 'Florida': 27, 'Utah': 4, 'Virginia': 11, 'Alaska': 1, 'New Mexico': 3, 'Ohio': 16, 'Oregon': 5, 'Hawaii': 2, 'Indiana': 9, 'North Carolina': 13, 'New York': 27, 'Delaware': 1, 'Minnesota': 8, 'West Virginia': 3, 'New Hampshire': 2, 'Arkansas': 4, 'Montana': 1, 'Georgia': 14, 'Connecticut': 5, 'Rhode Island': 2, 'Mississippi': 4, 'Washington': 10, 'North Dakota': 1}
>>> verdeling(vs2010, 1024)
{'Oklahoma': 12, 'Illinois': 43, 'Pennsylvania': 42, 'Iowa': 10, 'Maine': 4, 'South Dakota': 3, 'Nebraska': 6, 'New Jersey': 29, 'Maryland': 19, 'Texas': 84, 'Alabama': 16, 'Idaho': 5, 'South Carolina': 15, 'Michigan': 33, 'Tennessee': 21, 'Kansas': 9, 'Wyoming': 2, 'Wisconsin': 19, 'Louisiana': 15, 'Nevada': 9, 'Vermont': 2, 'Massachusetts': 22, 'Kentucky': 14, 'California': 124, 'Missouri': 20, 'Colorado': 17, 'Arizona': 21, 'Florida': 63, 'Utah': 9, 'Virginia': 27, 'Alaska': 2, 'New Mexico': 7, 'Ohio': 38, 'Oregon': 13, 'Hawaii': 5, 'Indiana': 22, 'North Carolina': 32, 'New York': 64, 'Delaware': 3, 'Minnesota': 18, 'West Virginia': 6, 'New Hampshire': 4, 'Arkansas': 10, 'Montana': 3, 'Georgia': 32, 'Connecticut': 12, 'Rhode Island': 4, 'Mississippi': 10, 'Washington': 22, 'North Dakota': 2}
>>> verdeling(vs2010, 42)
Traceback (most recent call last):
AssertionError: te weinig vertegenwoordigers
>>> vs1900 = inwoners(1900, 'vs_bevolkingsaantal.csv11')
Traceback (most recent call last):
AssertionError: geen gegevens beschikbaar