Last active
January 11, 2026 02:07
-
-
Save benprew/4328b6d38c01d7e35bfc77671bda430a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import csv | |
| import sys | |
| from typing import List, Dict | |
| def main(): | |
| file_path = sys.argv[1] | |
| candidates, votes = votes_from_csv(file_path) | |
| bcounts = borda_counts(candidates, votes) | |
| # Calculate the winner | |
| winner = condorcet_winner(candidates, votes) | |
| if winner is None: | |
| print("No Condorcet winner found.") | |
| winner = max(bcounts, key=bcounts.get) | |
| print("The winner is:", winner) | |
| print("For removing topics") | |
| print("Ranked results:") | |
| print(sorted(bcounts.items(), key=lambda x: x[1])) | |
| def votes_from_csv(file_path): | |
| # Read the CSV file | |
| with open(file_path, "r") as csvfile: | |
| reader = csv.DictReader(csvfile) | |
| candidates = [field for field in reader.fieldnames if field != "VOTER"] | |
| votes = {} | |
| for row in reader: | |
| voter = row["VOTER"] | |
| rankings = [] | |
| for candidate, ranking in row.items(): | |
| if candidate != "VOTER" and ranking: | |
| rankings.append((candidate, int(ranking))) | |
| rankings.sort(key=lambda x: x[1]) | |
| votes[voter] = [candidate for candidate, _ in rankings] | |
| return candidates, votes | |
| def condorcet_winner(candidates: List[str], votes: Dict[str, List[str]]) -> str: | |
| """ | |
| Calculate the winner of the election using the Condorcet method. | |
| Args: | |
| candidates (list): List of candidates. | |
| votes (dict): | |
| - Keys are voter names, values are lists of ranked candidates. | |
| Returns: | |
| str: Name of the Condorcet winner, or None if there is no winner. | |
| """ | |
| # Initialize pairwise comparison dictionary | |
| pairwise_comparisons = { | |
| candidate: {other: 0 for other in candidates if other != candidate} | |
| for candidate in candidates | |
| } | |
| # Compare each candidate against every other candidate | |
| for rankings in votes.values(): | |
| ranked_candidates = set(rankings) | |
| for i, candidate in enumerate(rankings): | |
| for j in range(i + 1, len(rankings)): | |
| other_candidate = rankings[j] | |
| pairwise_comparisons[candidate][other_candidate] += 1 | |
| # Treat unranked candidates as ranked lower than any ranked candidates | |
| for candidate in candidates: | |
| if candidate not in ranked_candidates: | |
| for ranked_candidate in ranked_candidates: | |
| pairwise_comparisons[ranked_candidate][candidate] += 1 | |
| # Determine if there is a Condorcet winner | |
| for candidate in candidates: | |
| is_winner = True | |
| for other_candidate in candidates: | |
| if candidate != other_candidate: | |
| if ( | |
| pairwise_comparisons[candidate][other_candidate] | |
| <= pairwise_comparisons[other_candidate][candidate] | |
| ): | |
| is_winner = False | |
| break | |
| if is_winner: | |
| return candidate | |
| return None | |
| def borda_counts(candidates: List[str], votes: Dict[str, List[str]]) -> Dict[str, int]: | |
| """ | |
| Calculate the winner of the election using the Borda count method. | |
| Args: | |
| candidates (list): List of candidates. | |
| votes (dict): | |
| - Keys are voter names and values are lists of ranked candidates. | |
| Returns: | |
| Dict[str, int]: Dictionary of each candidate to their Borda score | |
| """ | |
| # Initialize a dictionary to store the Borda count for each candidate | |
| borda_counts = {candidate: 0 for candidate in candidates} | |
| num_candidates = len(candidates) | |
| # Assign points based on rankings | |
| for voter, rankings in votes.items(): | |
| for i, candidate in enumerate(rankings): | |
| borda_counts[candidate] += num_candidates - i - 1 | |
| # Determine the candidate with the highest Borda count | |
| return borda_counts | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment