diff --git a/.gitignore b/.gitignore index a1338d6..db04a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 .glide/ + +coverage.txt \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6a02a0e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +sudo: false +language: go +go: +- 1.10.x +script: +- go test -race -coverprofile=coverage.txt -covermode=atomic -v ./... +after_success: +- curl -sL https://codecov.io/bash | bash \ No newline at end of file diff --git a/README.md b/README.md index 7331168..b18301d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # combos +[![Build Status](https://travis-ci.org/notnil/combos.svg?branch=master)](https://travis-ci.org/notnil/combos) +[![Go Doc](https://godoc.org/github.com/notnil/combos?status.svg)](https://godoc.org/github.com/notnil/combos) +[![Go Report Card](https://goreportcard.com/badge/github.com/notnil/combos)](https://goreportcard.com/report/github.com/notnil/combos) +[![codecov](https://codecov.io/gh/notnil/combos/branch/master/graph/badge.svg)](https://codecov.io/gh/notnil/combos) + combos is a simple combinations package ## Usage @@ -15,6 +20,20 @@ import ( func main() { fmt.Println(combos.New(7, 5)) - // [[0 1 2 3 4] [0 1 2 3 5] [0 1 2 3 6] [0 1 2 4 5] [0 1 2 4 6] [0 1 25 6] [0 1 3 4 5] [0 1 3 4 6] [0 1 3 5 6] [0 1 4 5 6] [0 2 3 4 5] [0 2 3 4 6] [0 2 3 5 6] [0 2 4 5 6] [0 3 4 5 6] [1 2 3 4 5] [1 2 3 4 6] [1 2 3 5 6] [1 2 4 5 6] [1 3 4 5 6] [23 4 5 6]] + // [[0 1 2 3 4] [0 1 2 3 5] [0 1 2 3 6] [0 1 2 4 5] [0 1 2 4 6] [0 1 2 5 6] [0 1 3 4 5] [0 1 3 4 6] [0 1 3 5 6] [0 1 4 5 6] [0 2 3 4 5] [0 2 3 4 6] [0 2 3 5 6] [0 2 4 5 6] [0 3 4 5 6] [1 2 3 4 5] [1 2 3 4 6] [1 2 3 5 6] [1 2 4 5 6] [1 3 4 5 6] [2 3 4 5 6]] } ``` + +## Benchmark + +```bash +~ go test -bench=. -benchmem +goos: darwin +goarch: amd64 +pkg: github.com/notnil/combos +Benchmark10C2-8 500000 2628 ns/op 4080 B/op 62 allocs/op +Benchmark100C2-8 10000 219910 ns/op 556416 B/op 4980 allocs/op +Benchmark1000C2-8 20 89627977 ns/op 78746426 B/op 499554 allocs/op +PASS +ok github.com/notnil/combos 5.582s +``` \ No newline at end of file diff --git a/combos_benchmark_test.go b/combos_benchmark_test.go new file mode 100644 index 0000000..fedab60 --- /dev/null +++ b/combos_benchmark_test.go @@ -0,0 +1,19 @@ +package combos_test + +import ( + "testing" + + "github.com/notnil/combos" +) + +func Benchmark10C2(b *testing.B) { benchmarknCr(10, 2, b) } + +func Benchmark100C2(b *testing.B) { benchmarknCr(100, 2, b) } + +func Benchmark1000C2(b *testing.B) { benchmarknCr(1000, 2, b) } + +func benchmarknCr(n int, r int, b *testing.B) { + for i := 0; i < b.N; i++ { + combos.New(n, r) + } +} diff --git a/combos_test.go b/combos_test.go index b24205d..a344553 100644 --- a/combos_test.go +++ b/combos_test.go @@ -1,14 +1,43 @@ package combos_test import ( + "sort" "testing" "github.com/notnil/combos" ) -func TestCombinations(t *testing.T) { - results := combos.New(7, 5) - if len(results) != 21 { - t.Fatalf("expected %d results but got %d", 21, len(results)) +type combinationTest struct { + n int + r int + expected int +} + +var combinationTests = []combinationTest{ + {7, 5, 21}, + {7, 4, 35}, + {10, 2, 45}, + {100, 2, 4950}, + {1000, 2, 499500}, +} + +func TestCombinationsCount(t *testing.T) { + for _, ct := range combinationTests { + actual := combos.New(ct.n, ct.r) + if len(actual) != ct.expected { + t.Errorf("%dC%d: expected %d, actual %d", ct.n, ct.r, ct.expected, len(actual)) + } + } +} +} + +func TestCombinationsOrdering(t *testing.T) { + for _, ct := range combinationTests { + actual := combos.New(ct.n, ct.r) + for _, combination := range actual { + if !sort.IntsAreSorted(combination) { + t.Errorf("%v combination is not in ascending order", combination) + } + } } }