Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

coverage.txt
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
```
19 changes: 19 additions & 0 deletions combos_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
37 changes: 33 additions & 4 deletions combos_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
}