Skip to content

Instantly share code, notes, and snippets.

@petrkotek
Last active December 30, 2016 16:00
Show Gist options
  • Save petrkotek/317dbcf6a73387682bc8d899b09c36df to your computer and use it in GitHub Desktop.
Save petrkotek/317dbcf6a73387682bc8d899b09c36df to your computer and use it in GitHub Desktop.
Combining (Aggregating/Adding/Subtracting) ranges in Golang
package ranges
import (
"math"
"sort"
)
type Range struct {
From int64
To int64
Value int64
}
type Aggregator interface {
Aggregate([]*Range) ([]*Range, error)
}
type StandardAggregator struct{}
func (a *StandardAggregator) Aggregate(ranges []*Range) ([]*Range, error) {
breakingPoints := make(map[int64]int64, 0)
outputRanges := make([]*Range, 0)
// 1. determine breaking points and store how much the value goes up or down at that point
// store the changes in a `steps` map
for _, inputRange := range ranges {
newValFrom := inputRange.Value
valFrom, ok := breakingPoints[inputRange.From]
if ok {
newValFrom += valFrom
}
breakingPoints[inputRange.From] = newValFrom
newValTo := -inputRange.Value
valTo, ok := breakingPoints[inputRange.To]
if ok {
newValTo += valTo
}
breakingPoints[inputRange.To] = newValTo
}
// 2. sort the breaking points in an increasing order
var stepKeys Int64Slice
for k := range breakingPoints {
stepKeys = append(stepKeys, k)
}
stepKeys.Sort()
// 3. iterate over the breaking points and generate output ranges
previousKey := int64(math.MinInt64)
previousValue := int64(0)
for _, currentKey := range stepKeys {
diff := breakingPoints[currentKey]
if diff == 0 {
// combine neighbor ranges with the same value
continue
}
if previousValue != 0 {
outputRanges = append(outputRanges, &Range{
From: previousKey,
To: currentKey,
Value: previousValue,
})
}
previousValue += diff
previousKey = currentKey
}
return outputRanges, nil
}
type Int64Slice []int64
func (p Int64Slice) Len() int {
return len(p)
}
func (p Int64Slice) Less(i, j int) bool {
return p[i] < p[j]
}
func (p Int64Slice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func (p Int64Slice) Sort() {
sort.Sort(p)
}
@petrkotek
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment