Added FindIntervalsForValue. Function renaming.

This commit is contained in:
Daniel Gil 2018-05-24 14:51:00 +02:00
parent 21187ac4df
commit 7255f129f5
3 changed files with 64 additions and 87 deletions

View File

@ -9,7 +9,7 @@ type Interval struct {
} }
func (itvl Interval) String() string { func (itvl Interval) String() string {
return fmt.Sprintf("(%v, %v) -> [%v]", itvl.Low, itvl.High, itvl.Object) return fmt.Sprintf("(%v, %v)", itvl.Low, itvl.High)
} }
// ByLow implements sort.Interface for []Interval based on the Low field. // ByLow implements sort.Interface for []Interval based on the Low field.

View File

@ -1,6 +1,7 @@
package interval_test package interval_test
import ( import (
"fmt"
"testing" "testing"
"bitbucket.org/differenttravel/interval" "bitbucket.org/differenttravel/interval"
@ -30,3 +31,33 @@ func TestInsert(t *testing.T) {
}) })
} }
} }
func TestFindIntervalsForValue(t *testing.T) {
itvls := interval.NewIntervals(0, 100)
itvls.Add(&interval.Interval{Low: 5, High: 7})
itvls.Add(&interval.Interval{Low: 2, High: 4})
itvls.Add(&interval.Interval{Low: 3, High: 6})
itvls.Add(&interval.Interval{Low: 18, High: 20})
itvls.Add(&interval.Interval{Low: 20, High: 30})
itvls.Add(&interval.Interval{Low: 25, High: 28})
itvls.Add(&interval.Interval{Low: 30, High: 32})
valueToFind1 := 2
matches1 := itvls.FindIntervalsForValue(valueToFind1)
matches1Txt := fmt.Sprintf("\nFind(value=%d)={", valueToFind1)
for _, m := range matches1 {
matches1Txt += fmt.Sprintf("%v,", m)
}
matches1Txt += "}"
t.Logf(matches1Txt)
valueToFind2 := 4
matches2 := itvls.FindIntervalsForValue(4)
matches2Txt := fmt.Sprintf("\nFind(value=%d)={", valueToFind2)
for _, m := range matches2 {
matches2Txt += fmt.Sprintf("%v,", m)
}
matches2Txt += "}"
t.Logf(matches2Txt)
}

View File

@ -12,12 +12,25 @@ const (
) )
type Intervals interface { type Intervals interface {
// Add appends a new interval
Add(itvl *Interval) Add(itvl *Interval)
// Sort sorts the intervals list by the Low property (ascending)
Sort() Sort()
GetGaps() []*Interval
GetOverlapped() []*Interval // Gaps first sorts (if necessary) and then returns the interval gaps
Gaps() []*Interval
// 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 Print() string
} }
type intervals struct { type intervals struct {
Intervals []*Interval Intervals []*Interval
MinLow int MinLow int
@ -43,6 +56,16 @@ func (intvls *intervals) Add(itvl *Interval) {
intvls.Sorted = false intvls.Sorted = false
} }
func (intvls *intervals) FindIntervalsForValue(value int) []*Interval {
var matches []*Interval
for _, intvl := range intvls.Intervals {
if inBetweenInclusive(value, intvl.Low, intvl.High) {
matches = append(matches, intvl)
}
}
return matches
}
func (intvls *intervals) Sort() { func (intvls *intervals) Sort() {
if !intvls.Sorted { if !intvls.Sorted {
sort.Sort(ByLow(intvls.Intervals)) sort.Sort(ByLow(intvls.Intervals))
@ -50,7 +73,7 @@ func (intvls *intervals) Sort() {
intvls.Sorted = true intvls.Sorted = true
} }
func (intvls *intervals) GetGaps() []*Interval { func (intvls *intervals) Gaps() []*Interval {
intvls.Sort() intvls.Sort()
gaps := []*Interval{} gaps := []*Interval{}
lastHigh := intvls.MinLow lastHigh := intvls.MinLow
@ -66,7 +89,7 @@ func (intvls *intervals) GetGaps() []*Interval {
return gaps return gaps
} }
func (intvls *intervals) GetOverlapped() []*Interval { func (intvls *intervals) Overlapped() []*Interval {
intvls.Sort() intvls.Sort()
list := []*Interval{} list := []*Interval{}
lastMinLow := math.MaxInt64 lastMinLow := math.MaxInt64
@ -102,11 +125,13 @@ func (intvls *intervals) isAnOverlap(value int, overlapped []*Interval) bool {
func (intvls *intervals) Print() string { func (intvls *intervals) Print() string {
intvls.Sort() intvls.Sort()
// Available Symbols: ( ◯ ◌ ◍ ◎ ● ◉ ) , ( □ ■ ), ( ░ ▒ ▓ █ ) // Available Symbols: ( ◯ ◌ ◍ ◎ ● ◉ ) , ( □ ■ ), ( ░ ▒ ▓ █ )
emptySymbol := "◌" emptySymbol := "◌"
fullSymbol := "◎" fullSymbol := "◎"
overlapSymbol := "●" overlapSymbol := "●"
separator := "║" separator := "║"
introText := fmt.Sprintf("\n==================================\n SUMMARY (minLow=%d, maxHigh=%d)\n==================================", intvls.MinLow, intvls.MaxHigh) 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) legend := fmt.Sprintf("\n • Legend: %v (empty), %v (full), %v (overlap)", emptySymbol, fullSymbol, overlapSymbol)
intervalText := "\n • Intervals: " intervalText := "\n • Intervals: "
@ -117,7 +142,7 @@ func (intvls *intervals) Print() string {
blockSize := 10 blockSize := 10
numSeparators := 0 numSeparators := 0
overlapped := intvls.GetOverlapped() overlapped := intvls.Overlapped()
for i, ovrlp := range overlapped { for i, ovrlp := range overlapped {
if i != 0 { if i != 0 {
overlapText += ", " overlapText += ", "
@ -152,7 +177,7 @@ func (intvls *intervals) Print() string {
} }
} }
} }
gaps := intvls.GetGaps() gaps := intvls.Gaps()
for i, gap := range gaps { for i, gap := range gaps {
if i != 0 { if i != 0 {
gapsText += ", " gapsText += ", "
@ -169,84 +194,5 @@ func (intvls *intervals) Print() string {
} }
axisLegend += fmt.Sprintf("%v", intvls.MaxHigh) axisLegend += fmt.Sprintf("%v", intvls.MaxHigh)
graphText := fmt.Sprintf("\n\n%s\n╠%s╣", axisLegend, graph) graphText := fmt.Sprintf("\n\n%s\n╠%s╣", axisLegend, graph)
return introText + legend + intervalText + gapsText + overlapText + graphText return "\n" + introText + legend + intervalText + gapsText + overlapText + graphText + "\n"
} }
// func (i *Intervals) Insert(intvl *Interval) {
// i.Intervals = append(i.Intervals, intvl)
// if i.Root == nil {
// // create the root node
// i.Root = &Node{Value: intvl, Left: nil, Right: nil}
// } else {
// currentNode := i.Root
// // search for the next block or the last
// for {
// next := currentNode.Next()
// if next == nil {
// // append the new interval to the right of the last element
// if intvl.Low >= currentNode.Value.Low {
// currentNode.Right = &Node{Value: intvl, Left: currentNode, Right: nil}
// } else {
// newNode := &Node{Value: intvl, Left: currentNode.Left, Right: currentNode}
// currentNode.Left = newNode
// }
// return
// } else if currentNode.OverlapsWith(intvl) {
// if intvl.Low >= next.Value.Low {
// // insert the new interval to the right of the current node
// newNode := &Node{Value: intvl, Left: currentNode, Right: currentNode.Right}
// currentNode.Right = newNode
// } else {
// // insert the new interval to the left of the current node
// newNode := &Node{Value: intvl, Left: currentNode.Left, Right: currentNode}
// currentNode.Left = newNode
// }
// }
// }
// }
// }
// func (i *Intervals) appendInterval(intvl *Interval, n *Node) {
// if intvl.Low >= n.Value.Low {
// // insert the new interval to the right of the current node
// newNode := &Node{Value: intvl, Left: currentNode, Right: currentNode.Right}
// currentNode.Right = newNode
// } else {
// // insert the new interval to the left of the current node
// newNode := &Node{Value: intvl, Left: currentNode.Left, Right: currentNode}
// currentNode.Left = newNode
// }
// }
// func (i *intervals) Print() string {
// emptySymbol := "░"
// fullSymbol := "█" // '▒' '▓'
// separator := "║"
// text := ""
// graph := "╠"
// index := 0
// for i, intvl := range i.Intervals {
// if i != 0 {
// text += ", "
// }
// text += fmt.Sprintf("[%d,%d]", intvl.Low, intvl.High)
// for i := index; i < intvl.Low; i++ {
// index++
// graph += emptySymbol
// if index%10 == 0 {
// graph += separator
// }
// }
// for i := index; i < intvl.High; i++ {
// index++
// graph += fullSymbol
// if index%10 == 0 {
// graph += separator
// }
// }
// }
// return text + "\n" + graph + "╣"
// }