function Apportionment()
clc
% Set up the data...
N = 435;
n = 50;
[State,P2012,P2010,P2000] = GetData();
P = sum(P2010);
% Compute the apportionment 5 ways
dS = Deal(P2010,N,@SmallestDivisors); eS = (P/435)./(P2010./dS);
dL = Deal(P2010,N,@LargestDivisors);  eL = (P/435)./(P2010./dL);
dM = Deal(P2010,N,@MajorFractions);   eM = (P/435)./(P2010./dM);
dE = Deal(P2010,N,@EqualProportions); eE = (P/435)./(P2010./dE);
dH = Deal(P2010,N,@HarmonicMean);     eH = (P/435)./(P2010./dH);
disp('S = Smallest Divisors     Priority function = p(i)/d(i) = alfa')
disp('L = Largest Divisors      Priority function = p(i)/(d(i)+1) = beta')
disp('M = Major Fractions       Priority function = (alfa+beta)/2')
disp('E = Equal Proportions     Priority function = sqrt(alfa*beta)')
disp('S = Harmonic Mean         Priority function = 2/(1/alfa + 1/beta)')
disp(' ')
disp('                  #Districts                      Citizen Weight '             )
disp('                 S  L  M  E  S         S        L        M        E        S    ')
for k=1:n
    fprintf('%s  %2d %2d %2d %2d %2d',State{k},dS(k),dL(k),dM(k),dE(k),dH(k))
    fprintf('     %7.4f  %7.4f  %7.4f  %7.4f  %7.4f\n',eS(k),eL(k),eM(k),eE(k),eH(k))
end
fprintf('\n\nAverage Departure from ideal citizen weight (which is 1)...\n\n')
qualS = sum((abs(eS - 1).*P2010)/P);
qualL = sum((abs(eL - 1).*P2010)/P);
qualM = sum((abs(eM - 1).*P2010)/P);
qualE = sum((abs(eE - 1).*P2010)/P);
qualH = sum((abs(eH - 1).*P2010)/P);
fprintf('    Smallest Divisor:  %7.5f\n',qualS)
fprintf('    Largest Divisor:   %7.5f\n',qualL)
fprintf('    Major Fractions:   %7.5f\n',qualM)
fprintf('    Equal Proportions: %7.5f\n',qualE)
fprintf('    Harmonic Mean:     %7.5f\n',qualH)


%  Last District computation...
[d,Last,Next] = Deal(P2010,N,@EqualProportions);
LastState = State{Last};
LastPop = P2010(Last);
LastD = d(Last)-1;
LastPriority = EqualProportions(LastPop,LastD);
NextState = State{Next};
NextPop = P2010(Next);
NextD = d(Next);
NextPriority = EqualProportions(NextPop,NextD);
fprintf('\n\nMethod of Equal Proportions\nWho gets the 435th district?\n')
fprintf('The situation before dealing out the last district...\n\n')
fprintf('  State           Population     #Districts so far    Priority Value\n')   
fprintf('\n %s    %8d          %2d                  %8.1f\n',LastState,LastPop,LastD,LastPriority)
fprintf(' %s    %8d          %2d                  %8.1f\n',NextState,NextPop,NextD,NextPriority)
tau = sqrt( (LastD*(LastD+1))/(NextD*(NextD+1))    );
x = round((LastPop - tau*NextPop)/(1+tau));
fprintf('\n\nThere would be a tie if %1d people moved from %s\n',x,LastState)
fprintf('to %s.\n',NextState)



function [d,Last,Next] = Deal(p,N,f)
n = length(p);
d = ones(n,1);
for k=1:N-n-1
    [m,i] = max(f(p,d));
    d(i) = d(i)+1;
end
[m,idx] = sort(f(p,d),'descend');
Last = idx(1);
Next = idx(2);
d(Last) = d(Last)+1;


function v = SmallestDivisors(p,d)
v = p./d;

function v = LargestDivisors(p,d)
v = p./(d+1);

function v = MajorFractions(p,d)
v = (p./d + p./(d+1))/2;

function v = EqualProportions(p,d)
v = sqrt((p./d).*(p./(d+1)));

function v = HarmonicMean(p,d)
v = 2./(d./p + (d+1)./p);

function [State,P2012,P2010,P2000] = GetData()

C = {...
  'Alabama        4822023   4779736   4447100',...
  'Alaska          731449    710231    626932',...
  'Arizona        6553255   6392017   5130632',...
  'Arkansas       2949131   2915918   2673400',...
  'California    38041430  37253956  33871648',...
  'Colorado       5187582   5029196   4301261',...
  'Connecticut    3590347   3574097   3405565',...
  'Delaware        917092    897934    783600',...
  'Florida       19317568  18801310  15982378',...
  'Georgia        9919945   9687653   8186453',...
  'Hawaii         1392313   1360301   1211537',...
  'Idaho          1595728   1567582   1293953',...
  'Illinois      12875255  12830632  12419293',...
  'Indiana        6537334   6483802   6080485',...
  'Iowa           3074186   3046355   2926324',...
  'Kansas         2885905   2853118   2688418',...
  'Kentucky       4380415   4339367   4041769',...
  'Louisiana      4601893   4533372   4468976',...
  'Maine          1329192   1328361   1274923',...
  'Maryland       5884563   5773552   5296486',...
  'Massachusetts  6646144   6547629   6349097',...
  'Michigan       9883360   9883640   9938444',...
  'Minnesota      5379139   5303925   4919479',...
  'Mississippi    2984926   2967297   2844658',...
  'Missouri       6021988   5988927   5595211',...
  'Montana        1005141    989415    902195',...
  'Nebraska       1855525   1826341   1711263',...
  'Nevada         2758931   2700551   1998257',...
  'New Hampshire  1320718   1316470   1235786',...
  'New Jersey     8864590   8791894   8414350',...
  'New Mexico     2085538   2059179   1819046',...
  'New York      19570261  19378102  18976457',...
  'North Carolina 9752073   9535483   8049313',...
  'North Dakota    699628    672591    642200',...
  'Ohio          11544225  11536504  11353140',...
  'Oklahoma       3814820   3751351   3450654',...
  'Oregon         3899353   3831074   3421399',...
  'Pennsylvania  12763536  12702379  12281054',...
  'Rhode Island   1050292   1052567   1048319',...
  'South Carolina 4723723   4625364   4012012',...
  'South Dakota    833354    814180    754844',...
  'Tennessee      6456243   6346105   5689283',...
  'Texas         26059203  25145561  20851820',...              
  'Utah           2855287   2763885   2233169',...
  'Vermont         626011    625741    608827',...
  'Virginia       8185867   8001024   7078515',...
  'Washington     6897012   6724540   5894121',...
  'West Virginia  1855413   1852994   1808344',...
  'Wisconsin      5726398   5686986   5363675',...
  'Wyoming         576412    563626    493782',...               
  };
P2012 = zeros(50,1);
P2010 = zeros(50,1);
P2000 = zeros(50,1);
for k=1:50
   S = C{k};
   State{k} = S(1:14);
   P2012(k) = str2num(S(15:22));
   P2010(k) = str2num(S(25:32));
   P2000(k) = str2num(S(35:42));
end

