The United States counts its citizens every ten years, and the result of that census is used to allocate the 435 congressional seats in the House of Representatives to the 50 states. Since 1940, that allocation has been done using a method devised by Edward Vermilye Huntington and Joseph Adna Hill.

United States Census Bureau

The Huntington-Hill method begins by assigning one representative to each state. Then each of the remaining representatives is assigned to a state in a succession of rounds by computing \[g(n, p) = \frac{p}{\sqrt{n(n+1)}}\] for each state, where $$n$$ is the current number of representatives (initially 1) and $$p$$ is the population of the state. This way, the value $$g(n, p)$$ represents the state's population divided by the geometric mean of the current number of representatives and the number of representatives the state would have if it was assigned the next representative. The geometric mean $$g(n, p)$$ is calculated for each state at each round and the next representative is assigned to the state with the highest geometric mean $$g(n, p)$$.

For instance, once each state has been assigned one representative, the geometric mean $$g(n, p)$$ for each state is its population divided the square root of 2. Since California has the biggest population, it gets the 51st representative. Then its geometric mean $$g(n, p)$$ is recalculated as its population divided by the square root of $$2 \times 3 = 6$$. In the second round the 52nd representative is assigned to Texas, which has the second-highest population, since it now has the largest geometric mean $$g(n, p)$$. This continues for $$435 - 50 = 385$$ rounds until all the representatives have been assigned.

Assignment

We will work with comma-separated values files (CSV-files) that contain the results of one or more censuses. The first column contains the names of the regions (e.g. the states of the United States) whose population counts are reported. Each remaining column contains the population count per region for the census in the year indicated in the column header. As an example, here are the first few lines of such a CSV-file:

REGION,1910,1920,1930,1940,1950,1960,1970,1980,1990,2000,2010,2020
Alabama,2138093,2348174,2646248,2832961,3061743,3266740,3444165,3893888,4040587,4447100,4779736,5024279
Alaska,64356,55036,59278,72524,128643,226167,300382,401851,550043,626932,710231,733391
Arizona,204354,334162,435573,499261,749587,1302161,1770900,2718215,3665228,5130632,6392017,7151502
Arkansas,1574449,1752204,1854482,1949387,1909511,1786272,1923295,2286435,2350725,2673400,2915918,3011524
California,2377549,3426861,5677251,6907387,10586223,15717204,19953134,23667902,29760021,33871648,37253956,39538223
Colorado,799024,939629,1035791,1123296,1325089,1753947,2207259,2889964,3294394,4301261,5029196,5773714
Connecticut,1114756,1380631,1606903,1709242,2007280,2535234,3031709,3107576,3287116,3405565,3574097,3605944
Delaware,202322,223003,238380,266505,318085,446292,548104,594338,666168,783600,897934,989948
Florida,752619,968470,1468211,1897414,2771305,4951560,6789443,9746324,12937926,15982378,18801310,21538187
…

Your task:

Example

In the following interactive session, we assume the CSV-file us_population.csv to be located in the current directory.

>>> us2010 = citizens(2010, 'us_population.csv')
>>> us2010['Alabama']
4779736
>>> us2010['Hawaii']
1360301
>>> us2010['Wyoming']
563626
>>> allocation(us2010, 435)
{'Alabama': 7, 'Alaska': 1, 'Arizona': 9, 'Arkansas': 4, 'California': 53, 'Colorado': 7, 'Connecticut': 5, 'Delaware': 1, 'Florida': 27, 'Georgia': 14, 'Hawaii': 2, 'Idaho': 2, 'Illinois': 18, 'Indiana': 9, 'Iowa': 4, 'Kansas': 4, 'Kentucky': 6, 'Louisiana': 6, 'Maine': 2, 'Maryland': 8, 'Massachusetts': 9, 'Michigan': 14, 'Minnesota': 8, 'Mississippi': 4, 'Missouri': 8, 'Montana': 1, 'Nebraska': 3, 'Nevada': 4, 'New Hampshire': 2, 'New Jersey': 12, 'New Mexico': 3, 'New York': 27, 'North Carolina': 13, 'North Dakota': 1, 'Ohio': 16, 'Oklahoma': 5, 'Oregon': 5, 'Pennsylvania': 18, 'Rhode Island': 2, 'South Carolina': 7, 'South Dakota': 1, 'Tennessee': 9, 'Texas': 36, 'Utah': 4, 'Vermont': 1, 'Virginia': 11, 'Washington': 10, 'West Virginia': 3, 'Wisconsin': 8, 'Wyoming': 1}
>>> allocation(us2010, 1024)
{'Alabama': 16, 'Alaska': 2, 'Arizona': 21, 'Arkansas': 10, 'California': 124, 'Colorado': 17, 'Connecticut': 12, 'Delaware': 3, 'Florida': 63, 'Georgia': 32, 'Hawaii': 5, 'Idaho': 5, 'Illinois': 43, 'Indiana': 22, 'Iowa': 10, 'Kansas': 9, 'Kentucky': 14, 'Louisiana': 15, 'Maine': 4, 'Maryland': 19, 'Massachusetts': 22, 'Michigan': 33, 'Minnesota': 18, 'Mississippi': 10, 'Missouri': 20, 'Montana': 3, 'Nebraska': 6, 'Nevada': 9, 'New Hampshire': 4, 'New Jersey': 29, 'New Mexico': 7, 'New York': 64, 'North Carolina': 32, 'North Dakota': 2, 'Ohio': 38, 'Oklahoma': 12, 'Oregon': 13, 'Pennsylvania': 42, 'Rhode Island': 4, 'South Carolina': 15, 'South Dakota': 3, 'Tennessee': 21, 'Texas': 84, 'Utah': 9, 'Vermont': 2, 'Virginia': 27, 'Washington': 22, 'West Virginia': 6, 'Wisconsin': 19, 'Wyoming': 2}
>>> allocation(us2010, 42)
Traceback (most recent call last):
AssertionError: too few representatives

>>> us1900 = citizens(1900, 'us_population.csv')
Traceback (most recent call last):
AssertionError: no data available