A => input-1.2.csv +16 -0
@@ 0,0 1,16 @@
+A,B,C
+5,4,0
+4,1,5
+5,4,0
+5,4,0
+0,1,5
+0,1,5
+0,1,5
+5,4,0
+0,1,5
+4,1,5
+5,4,0
+5,4,0
+0,5,2
+0,1,5
+5,4,0
A => input-1.3.csv +16 -0
@@ 0,0 1,16 @@
+A,B,C
+5,4,0
+4,1,5
+5,4,0
+5,4,0
+0,1,5
+0,1,5
+0,1,5
+5,4,0
+0,1,5
+4,1,5
+5,4,0
+5,4,0
+0,5,3
+0,1,5
+5,4,0
A => input-1.4.csv +16 -0
@@ 0,0 1,16 @@
+A,B,C
+5,4,0
+4,1,5
+5,4,0
+5,4,0
+0,1,5
+0,1,5
+0,1,5
+5,4,0
+0,1,5
+4,1,5
+5,4,0
+5,4,0
+0,5,4
+0,1,5
+5,4,0
A => input-1.5.csv +16 -0
@@ 0,0 1,16 @@
+A,B,C
+5,4,0
+4,1,5
+5,4,0
+5,4,0
+0,1,5
+0,1,5
+0,1,5
+5,4,0
+0,1,5
+4,1,5
+5,4,0
+5,4,0
+0,4,5
+0,1,5
+5,4,0
M main.go +59 -30
@@ 12,7 12,6 @@ import (
"strings"
)
-// FIXME: detect tie
func main() {
/**************************/
/* Process the input data */
@@ 32,7 31,7 @@ func main() {
}
/*********************/
- /* The SBB algorithm */
+ /* The MARS algorithm */
/*********************/
// As defined, R is max-min.
@@ 50,38 49,26 @@ func main() {
ttl := total(ints, diffs)
// wc is the index of the final winner
wc := max(ttl)
- // Look for cycles
- past := make([]int, 0)
- for {
- d2 := diff(ints, wc, R)
- t2 := total(ints, d2)
- w2 := max(t2)
- // If the current max is the same as the previous max, then the algorithm has settled
- // on a winner.
- if w2 == wc {
- break
- }
- // Check to see if we've seen this winner before (but not immediately before); if so,
- // then we're looping; dump the cycle list and exit.
- for _, cand := range past {
- if w2 == cand {
- fmt.Print("Cycle found in adjusted scoring ")
- for _, c := range past {
- fmt.Printf("%s => ", lines[0][c])
- }
- fmt.Printf("%s => ...\n", lines[0][w2])
- printScoreDetails(w, lines, badVotes, ints, diffs, ttl)
- return
- }
- }
- // Add the current winner to the "seen before" list
- past = append(past, w2)
- // Set the "immediately previous" winner to the current winner for the next loop
- wc = w2
+ // Look for cycles; if cycle, highest score wints
+ cycle := checkCycle(lines[0], ints, wc, R)
+ if cycle {
+ printScoreDetails(w, lines, badVotes, ints, diffs, ttl)
+ // If there's a tie, then it's a hard tie
+ checkTie(lines[0], subtotal(ints), w)
+ return
}
printScoreDetails(wc, lines, badVotes, ints, diffs, ttl)
printAdjustDetails(wc, lines, badVotes, ints, diffs, ttl)
+ // If there's a tie in the adjusted score, use the pure score
+ if checkTie(lines[0], ttl, wc) {
+ // Report if there's a hard tie (both adjusted and pure)
+ if checkTie(lines[0], subtotal(ints), w) {
+ fmt.Println("Hard tie (no winner possible)")
+ return
+ }
+ fmt.Printf("Winner based on pure score: %s\n", lines[0][w])
+ }
}
// getRange finds the maximum and minimum score values in the entire file.
@@ 187,6 174,48 @@ func total(lines [][]int, diffs [][]int)
return ttls
}
+func checkTie(header []string, sttl []int, w int) bool {
+ var tie bool
+ for i, c := range sttl {
+ if sttl[w] == c && i != w {
+ fmt.Printf("Tie found between %s and %s\n", header[w], header[i])
+ tie = true
+ }
+ }
+ return tie
+}
+
+func checkCycle(header []string, ints [][]int, wc int, R int) bool {
+ past := make([]int, 0)
+ for {
+ d2 := diff(ints, wc, R)
+ t2 := total(ints, d2)
+ w2 := max(t2)
+ // If the current max is the same as the previous max, then the algorithm has settled
+ // on a winner.
+ if w2 == wc {
+ break
+ }
+ // Check to see if we've seen this winner before (but not immediately before); if so,
+ // then we're looping; dump the cycle list and exit.
+ for _, cand := range past {
+ if w2 == cand {
+ fmt.Print("Cycle found in adjusted scoring ")
+ for _, c := range past {
+ fmt.Printf("%s => ", header[c])
+ }
+ fmt.Printf("%s => ...\n", header[w2])
+ return true
+ }
+ }
+ // Add the current winner to the "seen before" list
+ past = append(past, w2)
+ // Set the "immediately previous" winner to the current winner for the next loop
+ wc = w2
+ }
+ return false
+}
+
/****************************************************************************************/
/* The functions below are all utility functions not relevant to the vote calculations; */
/* they print or convert arrays and values. */
M tie.csv => tie.1.csv +8 -8
@@ 1,9 1,9 @@
A,B,C
-5,1,0
-5,1,0
-5,1,0
-5,1,0
-0,1,5
-0,1,5
-0,1,5
-0,1,5
+5,2,0
+5,2,0
+5,2,0
+5,2,0
+0,2,5
+0,2,5
+0,2,5
+0,2,5
M tie.csv +8 -8
@@ 1,9 1,9 @@
A,B,C
-5,1,0
-5,1,0
-5,1,0
-5,1,0
-0,1,5
-0,1,5
-0,1,5
-0,1,5
+5,3,0
+5,3,0
+5,3,0
+5,3,0
+0,3,5
+0,3,5
+0,3,5
+0,3,5