def getDistribution(chain, electionName, electionStatistic="seats", party="Rep",
                    constraintFunction=(lambda x, y: True)):
    """Runs chain and returns (election statistic, plan) pairs
    
    Parameters:
    chain (MarkovChain): chain to be run
    electionName (String): name of election to determine election statistic
    electionStatistic (String): String corresponding to desired electoral statistic
    party: Party to which electoral statistic is with respect to (only applicable
           to "seats" and "wins"- else party is determined by first party listed
           in Election for chain)
    constraintFunction (function): function, which takes a plan and the index 
    in the chain as arguments, used to constrain which plans generated by chain
    are added to the distribution. By default, adds all plans.
    """
    
    plans = []
    for i, plan in enumerate(chain): # Runs chain
        # If constraintFunction is True, add appropriate tuple to list
        if (constraintFunction(plan, i)):
            if (electionStatistic=="seats" or electionStatistic=="won"):
                plans.append((plan[electionName].seats(party), plan))
            elif (electionStatistic=="efficiency_gap"):
                plans.append((plan[electionName].efficiency_gap(), plan))
            elif (electionStatistic=="mean_median"):
                plans.append((plan[electionName].mean_median(), plan))
            elif (electionStatistic=="mean_thirdian"):
                plans.append((plan[electionName].mean_thirdian(), plan))
            elif (electionStatistic=="partisan_bias"):
                plans.append((plan[electionName].partisan_bias(), plan))
            elif (electionStatistic=="partisan_gini"):
                plans.append((plan[electionName].partisan_gini(), plan))
            
    return plans