diff --git a/src/numbers.rs b/src/numbers.rs index 07d0fe5..6f52621 100644 --- a/src/numbers.rs +++ b/src/numbers.rs @@ -158,9 +158,7 @@ impl ops::Rem for Rational { impl ops::Add<&Rational> for Rational { type Output = Rational; - fn add(self, _rhs: &Rational) -> Self::Output { - todo!() - } + fn add(self, rhs: &Rational) -> Self::Output { Rational(self.0 + &rhs.0) } } impl ops::Sub<&Rational> for Rational { diff --git a/src/stv/mod.rs b/src/stv/mod.rs index c7cb92a..877215a 100644 --- a/src/stv/mod.rs +++ b/src/stv/mod.rs @@ -89,15 +89,11 @@ fn next_preferences<'a, N: Number>(state: &CountState<'a, N>, votes: Vec(state: &mut CountState) { - let mut votes = Vec::new(); - for ballot in state.election.ballots.iter() { - let vote = Vote { - ballot: ballot, - value: ballot.orig_value.clone(), - up_to_pref: 0, - }; - votes.push(vote); - } + let votes = state.election.ballots.iter().map(|b| Vote { + ballot: b, + value: b.orig_value.clone(), + up_to_pref: 0, + }).collect(); let result = next_preferences(state, votes); @@ -117,10 +113,7 @@ pub fn distribute_first_preferences(state: &mut CountState) { pub fn calculate_quota(state: &mut CountState) { // Calculate the total vote - state.quota = N::zero(); - for count_card in state.candidates.values() { - state.quota += &count_card.votes; - } + state.quota = state.candidates.values().fold(N::zero(), |acc, cc| { acc + &cc.votes }); // TODO: Different quotas state.quota /= N::from(state.election.seats + 1); @@ -136,13 +129,10 @@ fn meets_quota(quota: &N, count_card: &CountCard) -> bool { } pub fn elect_meeting_quota(state: &mut CountState) { - // Can't use filter(...) magic because of conflict with borrow checker - let mut cands_meeting_quota = Vec::new(); - for (candidate, count_card) in state.candidates.iter_mut() { - if count_card.state == CandidateState::HOPEFUL && meets_quota(&state.quota, count_card) { - cands_meeting_quota.push((candidate, count_card)); - } - } + let quota = &state.quota; // Have to do this or else the borrow checker gets confused + let mut cands_meeting_quota: Vec<(&&Candidate, &mut CountCard)> = state.candidates.iter_mut() + .filter(|(_, cc)| cc.state == CandidateState::HOPEFUL && meets_quota(quota, cc)) + .collect(); if cands_meeting_quota.len() > 0 { // Sort by votes @@ -159,13 +149,9 @@ pub fn elect_meeting_quota(state: &mut CountState) { } pub fn distribute_surpluses(state: &mut CountState) -> bool where for<'r> &'r N: Sub<&'r N, Output=N> { - // As above regarding filter(...) - let mut has_surplus = Vec::new(); - for (candidate, count_card) in state.candidates.iter() { - if count_card.votes > state.quota { - has_surplus.push((candidate, count_card)); - } - } + let mut has_surplus: Vec<(&&Candidate, &CountCard)> = state.candidates.iter() + .filter(|(_, cc)| cc.votes > state.quota) + .collect(); if has_surplus.len() > 0 { // TODO: Different sorting orders @@ -229,12 +215,10 @@ fn distribute_surplus(state: &mut CountState, elected_candidate: & pub fn bulk_elect(state: &mut CountState) -> bool { if state.election.candidates.len() - state.num_excluded <= state.election.seats { // Bulk elect all remaining candidates - let mut hopefuls = Vec::new(); - for (candidate, count_card) in state.candidates.iter_mut() { - if count_card.state == CandidateState::HOPEFUL { - hopefuls.push((candidate, count_card)); - } - } + let mut hopefuls: Vec<(&&Candidate, &mut CountCard)> = state.candidates.iter_mut() + .filter(|(_, cc)| cc.state == CandidateState::HOPEFUL) + .collect(); + // TODO: Handle ties hopefuls.sort_unstable_by(|a, b| a.1.votes.partial_cmp(&b.1.votes).unwrap()); @@ -250,12 +234,9 @@ pub fn bulk_elect(state: &mut CountState) -> bool { } pub fn exclude_hopefuls(state: &mut CountState) -> bool { - let mut hopefuls = Vec::new(); - for (candidate, count_card) in state.candidates.iter() { - if count_card.state == CandidateState::HOPEFUL { - hopefuls.push((candidate, count_card)); - } - } + let mut hopefuls: Vec<(&&Candidate, &CountCard)> = state.candidates.iter() + .filter(|(_, cc)| cc.state == CandidateState::HOPEFUL) + .collect(); // Sort by votes // TODO: Handle ties @@ -269,12 +250,9 @@ pub fn exclude_hopefuls(state: &mut CountState) -> bool { } pub fn continue_exclusion(state: &mut CountState) -> bool { - let mut excluded_with_votes = Vec::new(); - for (candidate, count_card) in state.candidates.iter() { - if count_card.state == CandidateState::EXCLUDED && !count_card.votes.is_zero() { - excluded_with_votes.push((candidate, count_card)); - } - } + let mut excluded_with_votes: Vec<(&&Candidate, &CountCard)> = state.candidates.iter() + .filter(|(_, cc)| cc.state == CandidateState::EXCLUDED && !cc.votes.is_zero()) + .collect(); if excluded_with_votes.len() > 0 { excluded_with_votes.sort_unstable_by(|a, b| a.1.order_elected.partial_cmp(&b.1.order_elected).unwrap());