# HG changeset patch # User Sean E. Russell # Date 1613575847 21600 # Wed Feb 17 09:30:47 2021 -0600 # Node ID 395485d3f515db703ae122e77fd7237997626ff8 # Parent de460c03ed7a26df1a0dac9cae27495a5fb2b285 Adds headers to the input data, such that the first line lists the candidates. This makes comparing results between different datasets (with some candidates added or removed) easier. diff --git a/input-1.csv b/input-1.csv --- a/input-1.csv +++ b/input-1.csv @@ -1,3 +1,4 @@ +A,B,C 5,4,0 4,1,5 5,4,0 diff --git a/input-2.csv b/input-2.csv --- a/input-2.csv +++ b/input-2.csv @@ -1,3 +1,4 @@ +A,B,C 5,4,0 4,1,5 5,4,0 diff --git a/main.go b/main.go --- a/main.go +++ b/main.go @@ -23,7 +23,8 @@ panic(err) } // All of the row/column values are strings. Turn them into ints - ints, badVotes := toInts(lines) + // The first line is the header, and lists the candidates, so is excluded + ints, badVotes := toInts(lines[1:]) if len(badVotes) > 0 { fmt.Println("Vote errors encountered:") // We'll print info about the votes at the end. @@ -118,9 +119,6 @@ lls := row[lidx] dr := make([]int, len(row)) for c, cell := range row { - if c == lidx { - continue - } switch { case cell < lls: dr[c] = -r @@ -165,22 +163,24 @@ // printDetails cut out from main() to keep main terse; nothing here is // relevant to the voting calculation, and is only output. -func printDetails(wc int, lines, badVotes [][]string, ints [][]int, diffs [][]int, ttl []int) { +func printDetails(wc int, hlines, badVotes [][]string, ints [][]int, diffs [][]int, ttl []int) { + header := hlines[0] + lines := hlines[1:] // The rest of this is just dumping out the calculations. fmt.Printf("Total votes in input: %d\n", len(lines)) - printWithHeader("Summary of distributions", true, uniq(lines)) + printWithCandidates("Summary of distributions", true, header, uniq(lines)) subttl := subtotal(ints) - printWithHeader("Subtotals", false, subttl) + printWithCandidates("Subtotals", false, header, subttl) subWc := max(subttl) - fmt.Printf("Winner by score: %s with %d\n", toS(subWc), subttl[subWc]) - printWithHeader("Summary of diffs", true, uniq(toString(diffs))) - printWithHeader("Modifiers", false, subtotal(diffs)) - printWithHeader("Totals", false, ttl) - fmt.Printf("Highest combined total: %s with %d\n", toS(wc), ttl[wc]) + fmt.Printf("Winner by score: %s with %d\n", header[subWc], subttl[subWc]) + printWithCandidates("Summary of diffs", true, header, uniq(toString(diffs))) + printWithCandidates("Modifiers", false, header, subtotal(diffs)) + printWithCandidates("Totals", false, header, ttl) + fmt.Printf("Highest combined total: %s with %d\n", header[wc], ttl[wc]) if len(badVotes) > 0 { fmt.Printf("\n%d records were invalid.", len(badVotes)) - printWithHeader("The # column is the line number in the input file.", true, badVotes) + printWithCandidates("The # column is the line number in the input file.", true, header, badVotes) } } @@ -244,11 +244,11 @@ return strs } -// printWithHeader is a utility function to print out a matrix, with an +// printWithCandidates is a utility function to print out a matrix, with an // optional header where each column is a candidate (A, B, C, etc). Optionally, // the first column is a count of the number of votes that voted exactly // the same way. -func printWithHeader(d string, count bool, v interface{}) { +func printWithCandidates(d string, count bool, cands []string, v interface{}) { fmt.Println(d) switch a := v.(type) { case [][]string: @@ -257,7 +257,7 @@ return a[i][0] > a[j][0] }) } - printHeader(len(a[0]), count) + fmt.Printf(" \t%s\n", strings.Join(cands, "\t")) for _, r := range a { if !count { fmt.Printf(" \t") @@ -270,7 +270,7 @@ return a[i][0] > a[j][0] }) } - printHeader(len(a[0]), count) + fmt.Printf(" \t%s\n", strings.Join(cands, "\t")) for _, r := range a { if !count { fmt.Printf(" \t") @@ -286,7 +286,7 @@ return a[i] > a[j] }) } - printHeader(len(a), count) + fmt.Printf(" \t%s\n", strings.Join(cands, "\t")) if !count { fmt.Printf(" \t") } @@ -297,26 +297,3 @@ default: } } - -// printHeader prints a line of n candidates starting with candidate A. c -// determines whether or not the array contains a count as the first column -// of the number of votes in the first column. -func printHeader(n int, c bool) { - if c { - n -= 1 - } - fmt.Printf("#\t") - a := byte('A') - var i byte - m := byte(n) - for i = 0; i < m; i++ { - fmt.Printf("%s\t", string([]byte{a + i})) - } - fmt.Println() -} - -// toS converts a column index to a candidate string; column 0 is candidate A, -// column 1 is candidate B, and so on. 0-based. -func toS(b int) string { - return string([]byte{'A' + byte(b)}) -}