Skip to content

Commit

Permalink
Implement Invert/Normalize functions; bump 1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
justinfx committed Sep 17, 2015
1 parent 28a4bf1 commit 062106d
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 33 deletions.
127 changes: 118 additions & 9 deletions bench_test.go
Expand Up @@ -2,6 +2,8 @@ package fileseq

import (
"fmt"
"strconv"
"strings"
"testing"
)

Expand All @@ -19,6 +21,10 @@ func benchFrameSetCreate(b *testing.B, n int) {
}
}

func BenchmarkFrameSetCreate100x2(b *testing.B) { benchFrameSetCreate(b, 100) }
func BenchmarkFrameSetCreate100000x2(b *testing.B) { benchFrameSetCreate(b, 100000) }
func BenchmarkFrameSetCreate10000000x2(b *testing.B) { benchFrameSetCreate(b, 10000000) }

func benchFrameSetValue(b *testing.B, n int) {
r := fmt.Sprintf("1-%dx2", n)
fs, err := NewFrameSet(r)
Expand All @@ -34,6 +40,10 @@ func benchFrameSetValue(b *testing.B, n int) {
}
}

func BenchmarkFrameSetValue100x2(b *testing.B) { benchFrameSetValue(b, 100) }
func BenchmarkFrameSetValue100000x2(b *testing.B) { benchFrameSetValue(b, 100000) }
func BenchmarkFrameSetValue10000000x2(b *testing.B) { benchFrameSetValue(b, 10000000) }

func benchFrameSetIndex(b *testing.B, n int) {
r := fmt.Sprintf("1-%dx2", n)
fs, err := NewFrameSet(r)
Expand All @@ -52,6 +62,10 @@ func benchFrameSetIndex(b *testing.B, n int) {
}
}

func BenchmarkFrameSetIndex100x2(b *testing.B) { benchFrameSetIndex(b, 100) }
func BenchmarkFrameSetIndex100000x2(b *testing.B) { benchFrameSetIndex(b, 100000) }
func BenchmarkFrameSetIndex10000000x2(b *testing.B) { benchFrameSetIndex(b, 10000000) }

func benchFrameSetContains(b *testing.B, n int) {
r := fmt.Sprintf("1-%dx2", n)
fs, err := NewFrameSet(r)
Expand All @@ -71,15 +85,110 @@ func benchFrameSetContains(b *testing.B, n int) {
}
}

func BenchmarkFrameSetCreate100x2(b *testing.B) { benchFrameSetCreate(b, 100) }
func BenchmarkFrameSetCreate100000x2(b *testing.B) { benchFrameSetCreate(b, 100000) }
func BenchmarkFrameSetCreate10000000x2(b *testing.B) { benchFrameSetCreate(b, 10000000) }
func BenchmarkFrameSetValue100x2(b *testing.B) { benchFrameSetValue(b, 100) }
func BenchmarkFrameSetValue100000x2(b *testing.B) { benchFrameSetValue(b, 100000) }
func BenchmarkFrameSetValue10000000x2(b *testing.B) { benchFrameSetValue(b, 10000000) }
func BenchmarkFrameSetIndex100x2(b *testing.B) { benchFrameSetIndex(b, 100) }
func BenchmarkFrameSetIndex100000x2(b *testing.B) { benchFrameSetIndex(b, 100000) }
func BenchmarkFrameSetIndex10000000x2(b *testing.B) { benchFrameSetIndex(b, 10000000) }
func BenchmarkFrameSetContains100x2(b *testing.B) { benchFrameSetContains(b, 100) }
func BenchmarkFrameSetContains100000x2(b *testing.B) { benchFrameSetContains(b, 100000) }
func BenchmarkFrameSetContains10000000x2(b *testing.B) { benchFrameSetContains(b, 10000000) }

func benchFrameSetInvertedSingleRange(b *testing.B, n int) {
fs, err := NewFrameSet(fmt.Sprintf("%d-1x2", n))
if err != nil {
b.Fatal(err.Error())
}

b.ResetTimer()

for i := 0; i < b.N; i++ {
fs.InvertedFrameRange(4)
}
}

func BenchmarkFrameSetInvertedSingleRange100x2(b *testing.B) {
benchFrameSetInvertedSingleRange(b, 100)
}
func BenchmarkFrameSetInvertedSingleRange10000x2(b *testing.B) {
benchFrameSetInvertedSingleRange(b, 10000)
}
func BenchmarkFrameSetInvertedSingleRange100000x2(b *testing.B) {
benchFrameSetInvertedSingleRange(b, 100000)
}

func benchFrameSetInvertedCommaVals(b *testing.B, n int) {
var vals []string
for i := 1; i <= n; i++ {
vals = append(vals, strconv.Itoa(i))
i++
}
r := strings.Join(vals, `,`)
fs, err := NewFrameSet(r)
if err != nil {
b.Fatal(err.Error())
}

b.ResetTimer()

for i := 0; i < b.N; i++ {
fs.InvertedFrameRange(4)
}
}

func BenchmarkFrameSetInvertedCommaVals10x2(b *testing.B) {
benchFrameSetInvertedCommaVals(b, 10)
}
func BenchmarkFrameSetInvertedCommaVals1000x2(b *testing.B) {
benchFrameSetInvertedCommaVals(b, 1000)
}
func BenchmarkFrameSetInvertedCommaVals10000x2(b *testing.B) {
benchFrameSetInvertedCommaVals(b, 10000)
}

func benchFrameSetNormalizedSingleRange(b *testing.B, n int) {
fs, err := NewFrameSet(fmt.Sprintf("%d-1x2", n))
if err != nil {
b.Fatal(err.Error())
}

b.ResetTimer()

for i := 0; i < b.N; i++ {
fs.Normalize()
}
}

func BenchmarkFrameSetNormalizedSingleRange100x2(b *testing.B) {
benchFrameSetNormalizedSingleRange(b, 100)
}
func BenchmarkFrameSetNormalizedSingleRange10000x2(b *testing.B) {
benchFrameSetNormalizedSingleRange(b, 10000)
}
func BenchmarkFrameSetNormalizedSingleRange100000x2(b *testing.B) {
benchFrameSetNormalizedSingleRange(b, 100000)
}

func benchFrameSetNormalizedCommaVals(b *testing.B, n int) {
var vals []string
for i := 1; i <= n; i++ {
vals = append(vals, strconv.Itoa(i))
i++
}
r := strings.Join(vals, `,`)
fs, err := NewFrameSet(r)
if err != nil {
b.Fatal(err.Error())
}

b.ResetTimer()

for i := 0; i < b.N; i++ {
fs.Normalize()
}
}

func BenchmarkFrameSetNormalizedCommaVals10x2(b *testing.B) {
benchFrameSetNormalizedCommaVals(b, 10)
}
func BenchmarkFrameSetNormalizedCommaVals1000x2(b *testing.B) {
benchFrameSetNormalizedCommaVals(b, 1000)
}
func BenchmarkFrameSetNormalizedCommaVals10000x2(b *testing.B) {
benchFrameSetNormalizedCommaVals(b, 10000)
}
2 changes: 1 addition & 1 deletion fileseq.go
Expand Up @@ -27,7 +27,7 @@ import (
"strings"
)

const Version = "1.0.0"
const Version = "1.1.0"

var (
padding map[string]int
Expand Down
1 change: 1 addition & 0 deletions fileseq_test.go
Expand Up @@ -128,6 +128,7 @@ func TestFrameSetNormalize(t *testing.T) {
output string
}{
{"1,2,3,4,5", "1-5"},
{"5,1,4,2,3", "1-5"},
{"1-5,6,7,8,9,10,11-20", "1-20"},
}

Expand Down
11 changes: 4 additions & 7 deletions frameset.go
Expand Up @@ -200,10 +200,10 @@ func (s *FrameSet) FrameRangePadded(pad int) string {
return PadFrameRange(s.frange, pad)
}

// Inverted returns a new FrameSet that represents
// Invert returns a new FrameSet that represents
// all frames *not* within the current FrameSet. That is, it
// will create a range that "fills in" the current one.
func (s *FrameSet) Inverted() *FrameSet {
func (s *FrameSet) Invert() *FrameSet {
ptr := s.rangePtr.Inverted()
return &FrameSet{ptr.String(), ptr}
}
Expand All @@ -221,9 +221,6 @@ func (s *FrameSet) InvertedFrameRange(pad int) string {

// Normalize returns a new sorted and compacted FrameSet
func (s *FrameSet) Normalize() *FrameSet {
// TODO: Implement
return s

// ret, _ := NewFrameSet(FramesToFrameRange(s.frames, true, 0))
// return ret
ptr := s.rangePtr.Normalized()
return &FrameSet{ptr.String(), ptr}
}
51 changes: 35 additions & 16 deletions ranges/ranges.go
Expand Up @@ -528,30 +528,49 @@ func (l *InclusiveRanges) IterValues() Iterator {
// Original ordering is not preserved. New inverted range will be
// in an increasing value.
func (l *InclusiveRanges) Inverted() *InclusiveRanges {
inverted := &InclusiveRanges{}
return l.normalized(true)
}

// Normalized returns a new instance, where all values have
// been sorted and compacted (where possible)
func (l *InclusiveRanges) Normalized() *InclusiveRanges {
return l.normalized(false)
}

// Normalized returns a new instance, where all values have
// been sorted and compacted (where possible).
// If invert is true, then return all values within the start/end that
// are not in the current range.
func (l *InclusiveRanges) normalized(invert bool) *InclusiveRanges {
normalized := &InclusiveRanges{}

var (
start int
end int
step int
current int
pending int
contains bool
start int
end int
step int
current int
pending int
keepValue bool
)

// fmt.Println("Inverting ", l.String())
totalRange := NewInclusiveRange(l.Min(), l.Max(), 1)

checkValue := l.Contains
if !invert {
checkValue = func(value int) bool {
return !l.Contains(value)
}
}

for it := totalRange.IterValues(); !it.IsDone(); {

current = it.Next()

// fmt.Println("Checking:", current, "(pending:", pending, ")")
contains = l.Contains(current)
keepValue = checkValue(current)

// Short-circuit if we encounter a value that
// is already in the original sequence.
if contains {
// is not in the original sequence.
if keepValue {

// fmt.Println(" Existing value")

Expand All @@ -568,7 +587,7 @@ func (l *InclusiveRanges) Inverted() *InclusiveRanges {
// and start a new range.
if (current + 1 - end) != step {
// fmt.Println(" Step changed. Adding range:", start, end, step)
inverted.Append(start, end, step)
normalized.Append(start, end, step)
step = 1
start = current
pending = 0
Expand All @@ -584,7 +603,7 @@ func (l *InclusiveRanges) Inverted() *InclusiveRanges {
// we have and start a new range again.
if pending >= 2 && current-end != step {
// fmt.Println(" Step changed. Adding range:", start, end, step)
inverted.Append(start, end, step)
normalized.Append(start, end, step)
pending = 0
}

Expand All @@ -604,10 +623,10 @@ func (l *InclusiveRanges) Inverted() *InclusiveRanges {
// Flush the remaining values
if pending > 0 {
// fmt.Println(" Flushing and adding remaining range:", start, end, step)
inverted.Append(start, end, step)
normalized.Append(start, end, step)
}

return inverted
return normalized
}

// tracks the iteration state across a inclusiveRanges instance
Expand Down
31 changes: 31 additions & 0 deletions ranges/ranges_test.go
Expand Up @@ -319,3 +319,34 @@ func TestRangesInverted(t *testing.T) {
}
}
}

func TestRangesNormalized(t *testing.T) {
table := []struct {
params [][]int
expected string
}{
{ // 0
[][]int{{1, 1, 1}, {2, 2, 1}, {3, 3, 1}, {4, 4, 1}, {5, 5, 1}},
"1-5",
},
{ // 1
[][]int{{5, 5, 1}, {1, 1, 1}, {4, 4, 1}, {2, 2, 1}, {3, 3, 1}, {1, 1, 1}, {1, 1, 1}},
"1-5",
},
{ // 2
[][]int{{1, 5, 1}, {6, 6, 1}, {7, 7, 1}, {8, 8, 1}, {9, 9, 1}, {10, 10, 1}, {11, 20, 1}},
"1-20",
},
}

for i, tt := range table {
var r InclusiveRanges
for _, p := range tt.params {
r.Append(p[0], p[1], p[2])
}
actual := r.Normalized().String()
if actual != tt.expected {
t.Errorf("Test %d: got %q; expected %q", i, actual, tt.expected)
}
}
}

0 comments on commit 062106d

Please sign in to comment.