splited big file into smaller files by functionality
This commit is contained in:
192
intervals.go
192
intervals.go
@@ -1,9 +1,7 @@
|
||||
package interval
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -18,25 +16,37 @@ type Intervals interface {
|
||||
// Sort sorts the intervals list by the Low property (ascending)
|
||||
Sort()
|
||||
|
||||
// HasGaps returns true if exists gaps for the introduced intervals between MinLow and MaxHigh
|
||||
HasGaps() bool
|
||||
|
||||
// Gaps first sorts (if necessary) and then returns the interval gaps
|
||||
Gaps() []*Interval
|
||||
|
||||
// Merge first sorts (if necessary) and then fussion together overlapped intervals
|
||||
Merge() []*Interval
|
||||
|
||||
// HasOverlapped returns true if exists overlapping for the introduced intervals
|
||||
HasOverlapped() bool
|
||||
|
||||
// Overlapped first sorts (if necessary) and then returns the overlapped intervals
|
||||
Overlapped() []*Interval
|
||||
|
||||
// FindIntervalsForValue returns all the intervals which contains the passed value
|
||||
FindIntervalsForValue(value int) []*Interval
|
||||
|
||||
// Print first sorts (if necessary) and then displays graphically the interval sequence
|
||||
Print() string
|
||||
// Report first sorts (if necessary) and then creates a report of the interval sequence
|
||||
Report() string
|
||||
}
|
||||
|
||||
// intervals implements Intervals interface
|
||||
type intervals struct {
|
||||
Intervals []*Interval
|
||||
MinLow int
|
||||
MaxHigh int
|
||||
Sorted bool
|
||||
Intervals []*Interval
|
||||
GapsList []*Interval
|
||||
OverlappedList []*Interval
|
||||
MergeList []*Interval
|
||||
MinLow int
|
||||
MaxHigh int
|
||||
Sorted bool
|
||||
}
|
||||
|
||||
// NewIntervalsDefault is a constructor that returns an instance of the Intervals interface with default values
|
||||
@@ -53,169 +63,3 @@ func NewIntervals(minLow int, maxHigh int) Intervals {
|
||||
Sorted: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (intvls *intervals) Add(itvl *Interval) {
|
||||
intvls.Intervals = append(intvls.Intervals, itvl)
|
||||
intvls.Sorted = false
|
||||
}
|
||||
|
||||
func (intvls *intervals) FindIntervalsForValue(value int) []*Interval {
|
||||
intvls.Sort()
|
||||
var matches []*Interval
|
||||
for _, intvl := range intvls.Intervals {
|
||||
if intvl.Low > value {
|
||||
// due to the intervals are sorted, we can confirm that we will not find more matches
|
||||
break
|
||||
}
|
||||
if inBetweenInclusive(value, intvl.Low, intvl.High) {
|
||||
matches = append(matches, intvl)
|
||||
}
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
func (intvls *intervals) Sort() {
|
||||
if !intvls.Sorted {
|
||||
sort.Sort(ByLow(intvls.Intervals))
|
||||
}
|
||||
intvls.Sorted = true
|
||||
}
|
||||
|
||||
func (intvls *intervals) Gaps() []*Interval {
|
||||
intvls.Sort()
|
||||
gaps := []*Interval{}
|
||||
lastMaxHigh := intvls.MinLow
|
||||
for _, intvl := range intvls.Intervals {
|
||||
if intvl.Low > lastMaxHigh {
|
||||
gaps = append(gaps, &Interval{Low: lastMaxHigh, High: intvl.Low - 1})
|
||||
}
|
||||
// lastHigh = intvl.High + 1
|
||||
if intvl.High >= lastMaxHigh {
|
||||
lastMaxHigh = intvl.High + 1
|
||||
}
|
||||
}
|
||||
if lastMaxHigh < intvls.MaxHigh {
|
||||
gaps = append(gaps, &Interval{Low: lastMaxHigh, High: intvls.MaxHigh})
|
||||
}
|
||||
return gaps
|
||||
}
|
||||
|
||||
func (intvls *intervals) Overlapped() []*Interval {
|
||||
intvls.Sort()
|
||||
list := []*Interval{}
|
||||
lastMinLow := math.MaxInt64
|
||||
lastMaxHigh := math.MinInt64
|
||||
for i, intvl := range intvls.Intervals {
|
||||
if i > 0 {
|
||||
lowInBetween := inBetweenInclusive(lastMinLow, intvl.Low, intvl.High) || inBetweenInclusive(intvl.Low, lastMinLow, lastMaxHigh)
|
||||
highInBetween := inBetweenInclusive(lastMaxHigh, intvl.Low, intvl.High) || inBetweenInclusive(intvl.High, lastMinLow, lastMaxHigh)
|
||||
if lowInBetween || highInBetween {
|
||||
greaterLow := max(intvl.Low, lastMinLow)
|
||||
lowerHigh := min(intvl.High, lastMaxHigh)
|
||||
list = append(list, &Interval{Low: greaterLow, High: lowerHigh})
|
||||
}
|
||||
}
|
||||
if intvl.Low < lastMinLow {
|
||||
lastMinLow = intvl.Low
|
||||
}
|
||||
if intvl.High > lastMaxHigh {
|
||||
lastMaxHigh = intvl.High
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (intvls *intervals) isOverlapping(value int, overlapped []*Interval) bool {
|
||||
for _, ovrlp := range overlapped {
|
||||
if inBetweenInclusive(value, ovrlp.Low, ovrlp.High) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (intvls *intervals) Print() string {
|
||||
intvls.Sort()
|
||||
|
||||
// Available Symbols: ( ◯ ◌ ◍ ◎ ● ◉ ) , ( □ ■ ), ( ░ ▒ ▓ █ )
|
||||
emptySymbol := "◌"
|
||||
fullSymbol := "◎"
|
||||
overlapSymbol := "●"
|
||||
leadingSymbol := "├"
|
||||
trailingSymbol := "┤"
|
||||
separator := "|"
|
||||
|
||||
introText := fmt.Sprintf("\n==================================\n SUMMARY (minLow=%d, maxHigh=%d)\n==================================", intvls.MinLow, intvls.MaxHigh)
|
||||
legend := fmt.Sprintf("\n • Legend: %v (empty), %v (full), %v (overlap)", emptySymbol, fullSymbol, overlapSymbol)
|
||||
intervalText := "\n • Intervals: "
|
||||
gapsText := "\n • Gaps: "
|
||||
overlapText := "\n • Overlapped: "
|
||||
graph := ""
|
||||
index := intvls.MinLow
|
||||
blockSize := 10
|
||||
numSeparators := 0
|
||||
|
||||
overlapped := intvls.Overlapped()
|
||||
for i, ovrlp := range overlapped {
|
||||
if i != 0 {
|
||||
overlapText += ", "
|
||||
}
|
||||
overlapText += fmt.Sprintf("[%d,%d]", ovrlp.Low, ovrlp.High)
|
||||
}
|
||||
|
||||
for j, intvl := range intvls.Intervals {
|
||||
if j != 0 {
|
||||
intervalText += ", "
|
||||
}
|
||||
intervalText += fmt.Sprintf("[%d,%d]", intvl.Low, intvl.High)
|
||||
for i := index; i < intvl.Low; i++ {
|
||||
index++
|
||||
graph += emptySymbol
|
||||
if index%blockSize == 0 {
|
||||
graph += separator
|
||||
numSeparators++
|
||||
}
|
||||
}
|
||||
|
||||
for i := index; i <= intvl.High; i++ {
|
||||
if intvls.isOverlapping(index, overlapped) {
|
||||
graph += overlapSymbol
|
||||
} else {
|
||||
graph += fullSymbol
|
||||
}
|
||||
index++
|
||||
if index%blockSize == 0 {
|
||||
graph += separator
|
||||
numSeparators++
|
||||
}
|
||||
}
|
||||
}
|
||||
gaps := intvls.Gaps()
|
||||
for i, gap := range gaps {
|
||||
if i != 0 {
|
||||
gapsText += ", "
|
||||
}
|
||||
gapsText += fmt.Sprintf("[%d,%d]", gap.Low, gap.High)
|
||||
}
|
||||
|
||||
for i := index + 1; i < intvls.MaxHigh; i++ {
|
||||
graph += emptySymbol
|
||||
if i%blockSize == 0 {
|
||||
graph += separator
|
||||
numSeparators++
|
||||
}
|
||||
}
|
||||
axisLegend := " "
|
||||
numSeparators = 0
|
||||
for i := intvls.MinLow; i < intvls.MaxHigh/blockSize; i++ {
|
||||
mark := fmt.Sprintf("%d", i*blockSize)
|
||||
axisLegend += mark
|
||||
limit := (blockSize - len(mark)) + 1
|
||||
for j := 0; j < limit; j++ {
|
||||
axisLegend += " "
|
||||
}
|
||||
}
|
||||
axisLegend += fmt.Sprintf("%v", intvls.MaxHigh)
|
||||
graphText := fmt.Sprintf("\n\n%s\n%s%s%s", axisLegend, leadingSymbol, graph, trailingSymbol)
|
||||
return "\n" + introText + legend + intervalText + gapsText + overlapText + graphText + "\n"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user