Skip to content

Instantly share code, notes, and snippets.

@seh
Created November 20, 2013 20:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seh/7570012 to your computer and use it in GitHub Desktop.
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.
// 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))
}
}
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