@@ 7,6 7,7 @@ import (
"fmt"
"io"
"math/big"
+ "sort"
"sync"
"time"
@@ 290,4 291,66 @@ func printResults(result []byte, candidates []Candidate) {
}
}
}
+
+ // Schulze method computation
+ // https://en.wikipedia.org/wiki/Schulze_method#Implementation
+ min := func(x, y int) int {
+ if x < y {
+ return x
+ }
+ return y
+ }
+ max := func(x, y int) int {
+ if x > y {
+ return x
+ }
+ return y
+ }
+ p := make(map[int]map[int]int)
+ for i := range candidates {
+ for j := range candidates {
+ if i != j {
+ if p[i] == nil {
+ p[i] = make(map[int]int)
+ }
+ if result[i*n+j] > result[j*n+i] {
+ p[i][j] = int(result[i*n+j])
+ } else {
+ p[i][j] = 0
+ }
+ }
+ }
+ }
+ for i := range candidates {
+ for j := range candidates {
+ if i != j {
+ for k := range candidates {
+ if i != k && j != k {
+ p[j][k] = max(p[j][k], min(p[j][i], p[i][k]))
+ }
+ }
+ }
+ }
+ }
+ order := []int{}
+ for i := range candidates {
+ k := sort.Search(len(order), func(j int) bool {
+ return p[i][order[j]] > p[order[j]][i]
+ })
+ newOrder := make([]int, len(order)+1)
+ copy(newOrder[:k], order[:k])
+ newOrder[k] = i
+ copy(newOrder[k+1:], order[k:])
+ order = newOrder
+ }
+ fmt.Printf("\n=== Schulze Method Ranking ===\n")
+ for i:= 0; i < len(order); i++ {
+ rank := i+1 // don't want 0th place
+ fmt.Printf("%d) %s\n", rank, candidates[order[i]])
+ // candidates that are tied get the same rank
+ for i+1 < len(order) && p[order[i]][order[i+1]] == p[order[i+1]][order[i]] {
+ fmt.Printf("%d) %s\n", rank, candidates[order[i+1]])
+ i++
+ }
+ }
}