Skip to content

Instantly share code, notes, and snippets.

@joriki
Created April 2, 2020 05:36
Show Gist options
  • Save joriki/28232922bbf6f949082855f325a6c434 to your computer and use it in GitHub Desktop.
Save joriki/28232922bbf6f949082855f325a6c434 to your computer and use it in GitHub Desktop.
Apply various methods of apportioning seats in a parliament; see https://math.stackexchange.com/questions/3605591.
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import info.joriki.io.Util;
public class Question3605591 {
final static int nseats = 435;
final static int nstates = 50;
final static int ncensus = 11;
// This should be set to the name of a file that contains the data from Table 1 at
// https://www.census.gov/content/dam/Census/library/publications/2011/dec/c2010br-08.pdf
final static String censusFile = "<pathname>";
static class State {
String name;
int population;
int seats;
Map<Comparator<State>,Integer> apportionments = new HashMap<>();
public State(String name,int population,int seats) {
this.name = name;
this.population = population;
this.seats = seats;
}
public String toString() {
return "State [name=" + name + ", population=" + population + ", seats=" + seats + "]";
}
}
static abstract class ApportionmentComparator implements Comparator<State> {
public int compare(State s1,State s2) {
return (int) Math.signum(quotient(s2) - quotient(s1));
}
private double quotient (State s) {
if (!s.apportionments.containsKey(this))
s.apportionments.put(this, 0);
return s.population / divisor (s.apportionments.get(this));
}
abstract protected double divisor(int seats);
};
static class DeltaComparator extends ApportionmentComparator {
private double delta;
public DeltaComparator(double delta) {
this.delta = delta;
}
protected double divisor(int seats) {
return seats + delta;
}
}
static class HuntingtonHillComparator extends ApportionmentComparator {
protected double divisor(int seats) {
return Math.sqrt(seats * (seats + 1));
}
}
final static ApportionmentComparator [] comparators = {
new HuntingtonHillComparator(),
new DeltaComparator(0),
new DeltaComparator(1/2.),
new DeltaComparator(1),
};
static char [] data;
static int i;
public static void main(String [] args) throws IOException {
Set<State> states = new HashSet<>();
data = new String(Util.undump(censusFile)).replace("(X)","0").toCharArray();
outer:
for (i = 0;;) {
int beg = i;
while (Character.isAlphabetic(data [i]) || data [i] == ' ')
i++;
String name = new String(data,beg,i - beg);
while (!Character.isDigit(data [i]))
i++;
int population = readCommaDelimitedInteger();
readCommaDelimitedInteger(); // resident population
readCommaDelimitedInteger(); // overseas population
int r = i;
while (Character.isDigit(data [r]))
r++;
r -= i;
int ndigits = r / ncensus;
if (r % ncensus != 0 && data [i] < '4')
ndigits++;
int representatives = Integer.parseInt(new String(data,i,ndigits));
State state = new State(name, population, representatives);
states.add(state);
while (!Character.isAlphabetic(data [i])) {
i++;
if (i == data.length)
break outer;
}
}
if (states.size() != nstates)
throw new Error();
State [] stateArray = states.toArray(new State [nstates]);
Arrays.sort(stateArray,comparators [2]);
int rank = 0;
for (State state : stateArray)
System.out.println(++rank + " : " + state);
for (ApportionmentComparator comparator : comparators) {
Queue<State> queue = new PriorityQueue<>(comparator);
queue.addAll(states);
for (int seat = 0;seat < nseats;seat++) {
State state = queue.poll();
state.apportionments.put(comparator,state.apportionments.get (comparator) + 1);
queue.add(state);
}
}
for (Comparator<State> comparator : comparators)
if (comparator != comparators [0]) {
for (State state : states) {
int diff = state.apportionments.get(comparator) - state.apportionments.get(comparators [0]);
if (diff != 0)
System.out.println(diff + " " + state);
}
System.out.println();
}
for (Comparator<State> comparator : comparators) {
double s = 0;
double s2 = 0;
double total = 0;
for (State state : states) {
double weight = state.population;
double voterWeight = state.apportionments.get(comparator) / (double) state.population;
s += weight * voterWeight;
s2 += weight * (voterWeight * voterWeight);
total += weight;
}
s /= total;
s2 /= total;
System.out.println(s + " ± " + (Math.sqrt(s2 - s * s)));
}
}
private static int readCommaDelimitedInteger() {
int result = 0;
for (int ndigits = 0;;i++) {
if (data [i] == ',')
ndigits = 0;
else {
if (!Character.isDigit(data [i]))
throw new Error();
if (++ndigits > 3)
break;
result *= 10;
result += data [i] - '0';
}
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment