diff --git a/src/main.rs b/src/main.rs index 2f3dd02..216b448 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,12 @@ const VOTE_SEPARATOR: &str = "- Vote Separator -\n"; const ANIME_SEPARATOR: &str = " | "; const VALUE_SEPARATOR: &str = ","; +#[derive(PartialEq)] +enum ElectionResult { + Winner((usize, usize), usize), + Tie, +} + fn main() { let args: Vec = std::env::args().skip(1).collect(); if args.len() != 1 { @@ -48,6 +54,14 @@ fn select_winners( let mut r: Vec<((usize, usize), usize)> = Combinations::of_size(0..candidate_count, 2) .map(|v| (v[0], v[1])) .map(|c| single_election(c, votes)) + // Remove ties + .filter_map(|m| { + if let ElectionResult::Winner(relation, margin) = m { + Some((relation, margin)) + } else { + None + } + }) .collect(); r.sort_by_key(|e| e.1); let mut result = Vec::new(); @@ -60,7 +74,7 @@ fn select_winners( for _ in 0..amount_of_winners { let winner = (0..candidate_count) // Find new winners each time. - .filter(|c| !winners.contains(&c)) + .filter(|c| !winners.contains(c)) .map(|c| { ( c, @@ -85,7 +99,7 @@ fn select_winners( fn single_election( (candidate_a, candidate_b): (usize, usize), votes: &[Vec], -) -> ((usize, usize), usize) { +) -> ElectionResult { let (mut a_votes, mut b_votes): (usize, usize) = (0, 0); for vote in votes { if vote[candidate_a] == vote[candidate_b] { @@ -98,15 +112,17 @@ fn single_election( } } if a_votes > b_votes { - ( + ElectionResult::Winner( (candidate_a, candidate_b), a_votes.max(b_votes) - a_votes.min(b_votes), ) - } else { - ( + } else if a_votes < b_votes { + ElectionResult::Winner( (candidate_b, candidate_a), a_votes.max(b_votes) - a_votes.min(b_votes), ) + } else { + ElectionResult::Tie } } @@ -125,11 +141,41 @@ mod tests { use super::*; #[test] - fn connection_test() { + fn connection() { let graph = [(0, 1), (1, 2), (0, 2), (2, 3)]; assert!(connection_exists(&graph, (0, 3))); assert!(!connection_exists(&graph, (3, 0))); let graph = [(0, 1)]; assert!(!connection_exists(&graph, (3, 0))); } + + #[test] + fn votes() { + let candidates = ["Alice", "Bob", "Carol", "Dave"]; + let votes: Vec> = vec![ + vec![5, 4, 1, 0], + vec![5, 3, 2, 0], + vec![4, 5, 1, 0], + vec![5, 4, 0, 1], + vec![4, 3, 2, 0], + vec![5, 2, 1, 0], + vec![3, 5, 2, 0], + ]; + let winners = select_winners(&votes, candidates.len(), candidates.len()); + assert!(winners[0] == 0); + assert!(winners[3] == 3); + + let candidates = ["Alice", "Bob", "Carol"]; + let votes: Vec> = vec![ + vec![5, 3, 1], + vec![5, 3, 1], + vec![3, 5, 1], + vec![3, 5, 1], + vec![1, 3, 5], + vec![1, 3, 5], + vec![5, 1, 3], + ]; + let winners = select_winners(&votes, candidates.len(), candidates.len()); + assert!(winners[0] == 1); + } }