Created
November 20, 2013 20:00
-
-
Save seh/7570012 to your computer and use it in GitHub Desktop.
A function to find the count of the mode in a potentially multimodal data set.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package mode provides functions related to the statistical mode of | |
// a set of data, the mode being the value that occurs most frequently | |
// in such a set. | |
package mode | |
import "sort" | |
func sortedIntsFrom(input []int) []int { | |
// Don't bother with sort.IntsAreSorted(). | |
sorted := make([]int, len(input)) | |
copy(sorted, input) | |
sort.Ints(sorted) | |
return sorted | |
} | |
// Precondition: len(input) >= 2 | |
func countOfSortedInts(input []int) (count int, unique bool) { | |
seen := 1 | |
prev := input[0] | |
for _, cur := range input[1:] { | |
if cur == prev { | |
seen++ | |
} else { | |
switch { | |
case seen > count: | |
count = seen | |
unique = true | |
case seen == count: | |
unique = false | |
} | |
seen = 1 | |
prev = cur | |
} | |
} | |
// Was the last run significant? | |
switch { | |
case seen > count: | |
count = seen | |
unique = true | |
case seen == count: | |
unique = false | |
} | |
return | |
} | |
// CountOfInts computes the largest size of the sets of equivalent | |
// integers in the input sequence. | |
// | |
// It returns this count and indicates whether that count was unique; | |
// if the input sequence is multimodal, with more than one set of the | |
// same size tied as the largest, the count is not unique. | |
// | |
// If the input sequence is empty, the count is zero, but is still | |
// considered to be unique. | |
// | |
// NB: Return value "count" will be nonnegative, and is of type int | |
// (rather than uint) for parity with the built-in function len(). | |
func CountOfInts(input []int) (count int, unique bool) { | |
switch len(input) { | |
case 0: | |
return 0, true | |
case 1: | |
return 1, true | |
case 2: | |
if input[0] == input[1] { | |
return 2, true | |
} | |
return 1, false | |
default: | |
return countOfSortedInts(sortedIntsFrom(input)) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mode | |
import "testing" | |
func ensureCountEquals(t *testing.T, count, expected int) { | |
if count != expected { | |
t.Fatalf("Expected count of %d, but got %d instead.", expected, count) | |
} | |
} | |
func ensureUnique(t *testing.T, unique bool) { | |
if !unique { | |
t.Fatal("Expected count to be unique, but it was not.") | |
} | |
} | |
func ensureNotUnique(t *testing.T, unique bool) { | |
if unique { | |
t.Fatal("Expected count to not be unique, but it was.") | |
} | |
} | |
func TestEmptyInts(t *testing.T) { | |
count, unique := CountOfInts(nil) | |
ensureCountEquals(t, count, 0) | |
ensureUnique(t, unique) | |
} | |
func TestSingletonInt(t *testing.T) { | |
count, unique := CountOfInts([]int{1}) | |
ensureCountEquals(t, count, 1) | |
ensureUnique(t, unique) | |
} | |
func TestEqualPairOfInts(t *testing.T) { | |
input := []int{1, 1} | |
count, unique := CountOfInts(input) | |
ensureCountEquals(t, count, len(input)) | |
ensureUnique(t, unique) | |
} | |
func TestDistinctPairOfInts(t *testing.T) { | |
count, unique := CountOfInts([]int{1, 2}) | |
ensureCountEquals(t, count, 1) | |
ensureNotUnique(t, unique) | |
} | |
func TestEqualSequenceOfInts(t *testing.T) { | |
input := []int{1, 1, 1} | |
count, unique := CountOfInts(input) | |
ensureCountEquals(t, count, len(input)) | |
ensureUnique(t, unique) | |
} | |
func TestDistinctSequenceOfInts(t *testing.T) { | |
input := []int{1, 2, 3} | |
count, unique := CountOfInts(input) | |
ensureCountEquals(t, count, 1) | |
ensureNotUnique(t, unique) | |
} | |
func TestOverlappingSequenceOfInts(t *testing.T) { | |
for _, input := range [][]int{ | |
{3, 4, 4}, | |
{4, 3, 4}, | |
{4, 4, 3}} { | |
count, unique := CountOfInts(input) | |
ensureCountEquals(t, count, 2) | |
ensureUnique(t, unique) | |
} | |
} | |
func TestTwoPairsOfInts(t *testing.T) { | |
for _, input := range [][]int{ | |
{3, 3, 4, 4}, | |
{3, 4, 4, 3}, | |
{4, 4, 3, 3}, | |
{4, 3, 3, 4}, | |
{3, 4, 3, 4}, | |
{4, 3, 4, 3}} { | |
count, unique := CountOfInts(input) | |
ensureCountEquals(t, count, 2) | |
ensureNotUnique(t, unique) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment