diff --git a/merge.go b/merge.go index 8074c11..c259e18 100644 --- a/merge.go +++ b/merge.go @@ -12,21 +12,30 @@ func (intvls *intervals) calculateMerged() []*Interval { list := []*Interval{} var lastLow int var lastHigh int + pendingToAdd := false for i, intvl := range intvls.Intervals { if i == 0 { lastLow = intvl.Low lastHigh = intvl.High continue } - if inBetweenInclusive(intvl.Low, lastLow, lastHigh) { - // because the intervals are previously sorted, we just need to take care of the High value + if isLowInBetween(intvl.Low, intvl.High, lastLow, lastHigh) || isHighInBetween(intvl.Low, intvl.High, lastLow, lastHigh) { + if intvl.Low < lastLow { + lastLow = intvl.Low + } if intvl.High > lastHigh { lastHigh = intvl.High } + pendingToAdd = true continue } list = append(list, &Interval{Low: lastLow, High: lastHigh}) + lastLow = intvl.Low + lastHigh = intvl.High + pendingToAdd = false + } + if pendingToAdd == true { + list = append(list, &Interval{Low: lastLow, High: lastHigh}) } - list = append(list, &Interval{Low: lastLow, High: lastHigh}) return list } diff --git a/overlap.go b/overlap.go index 2401536..c7861d4 100644 --- a/overlap.go +++ b/overlap.go @@ -24,8 +24,8 @@ func (intvls *intervals) calculateOverlapped() []*Interval { 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) + lowInBetween := isLowInBetween(lastMinLow, lastMaxHigh, intvl.Low, intvl.High) //inBetweenInclusive(lastMinLow, intvl.Low, intvl.High) || inBetweenInclusive(intvl.Low, lastMinLow, lastMaxHigh) + highInBetween := isHighInBetween(lastMinLow, lastMaxHigh, intvl.Low, intvl.High) //inBetweenInclusive(lastMaxHigh, intvl.Low, intvl.High) || inBetweenInclusive(intvl.High, lastMinLow, lastMaxHigh) if lowInBetween || highInBetween { greaterLow := max(intvl.Low, lastMinLow) lowerHigh := min(intvl.High, lastMaxHigh) @@ -42,7 +42,7 @@ func (intvls *intervals) calculateOverlapped() []*Interval { return list } -func (intvls *intervals) isOverlapping(value int, overlapped []*Interval) bool { +func (intvls *intervals) valueIsOverlapping(value int, overlapped []*Interval) bool { for _, ovrlp := range overlapped { if inBetweenInclusive(value, ovrlp.Low, ovrlp.High) { return true diff --git a/report.go b/report.go index 74b3a57..e2af599 100644 --- a/report.go +++ b/report.go @@ -28,24 +28,35 @@ func newSymbols() symbols { func (intvls *intervals) Report() string { intvls.Sort() symbols := newSymbols() - intro := intvls.buildHeading(symbols) - index := intvls.MinLow - numSeparators := 0 + intro := intvls.buildHeading() + legend := intvls.buildLegend(symbols) overlapText := intvls.reportOverlapped() - intervalText := "" - graph := "" - intervalText, index, graph, numSeparators = intvls.reportIntervals(index, symbols, numSeparators) gapsText := intvls.reportGaps() - graph, numSeparators, index = intvls.fillUntilTheEnd(index, symbols, graph, numSeparators) + mergeText := intvls.reportMerged() + intervalText, graph := intvls.buildGraph(symbols) axisLegend := intvls.buildAxisLegend() - graphText := fmt.Sprintf("\n\n%s\n%s%s%s", axisLegend, symbols.leadingSymbol, graph, symbols.trailingSymbol) - return "\n" + intro + intervalText + gapsText + overlapText + graphText + "\n" + graphWithLegend := fmt.Sprintf("\n\n%s\n%s%s%s", axisLegend, symbols.leadingSymbol, graph, symbols.trailingSymbol) + return "\n" + intro + intervalText + gapsText + overlapText + mergeText + legend + graphWithLegend + "\n" } -func (intvls *intervals) buildHeading(symbols symbols) string { +func (intvls *intervals) buildGraph(symbols symbols) (string, string) { + index := intvls.MinLow + numSeparators := 0 + graph := "" + intervalText := "" + intervalText, index, graph, numSeparators = intvls.reportIntervals(index, symbols, numSeparators) + graph, numSeparators, index = intvls.fillUntilTheEnd(index, symbols, graph, numSeparators) + return intervalText, graph +} + +func (intvls *intervals) buildHeading() string { introText := fmt.Sprintf("\n==================================\n REPORT (minLow=%d, maxHigh=%d)\n==================================", intvls.MinLow, intvls.MaxHigh) + return introText +} + +func (intvls *intervals) buildLegend(symbols symbols) string { legend := fmt.Sprintf("\n • Legend: %v (empty), %v (full), %v (overlap)", symbols.emptySymbol, symbols.fullSymbol, symbols.overlapSymbol) - return introText + legend + return legend } func (intvls *intervals) reportIntervals(index int, symbols symbols, numSeparators int) (string, int, string, int) { @@ -66,7 +77,7 @@ func (intvls *intervals) reportIntervals(index int, symbols symbols, numSeparato } for i := index; i <= intvl.High; i++ { - if intvls.isOverlapping(index, intvls.OverlappedList) { + if intvls.valueIsOverlapping(index, intvls.OverlappedList) { graph += symbols.overlapSymbol } else { graph += symbols.fullSymbol @@ -116,6 +127,18 @@ func (intvls *intervals) reportGaps() string { return gapsText } +func (intvls *intervals) reportMerged() string { + mergedText := "\n • Merged: " + merged := intvls.Merge() + for i, merge := range merged { + if i != 0 { + mergedText += ", " + } + mergedText += fmt.Sprintf("[%d,%d]", merge.Low, merge.High) + } + return mergedText +} + func (intvls *intervals) buildAxisLegend() string { axisLegend := " " for i := intvls.MinLow; i < intvls.MaxHigh/blockSize; i++ { diff --git a/utils.go b/utils.go index 2248783..7199a14 100644 --- a/utils.go +++ b/utils.go @@ -26,3 +26,17 @@ func inBetweenExclusive(i, min, max int) bool { } return false } + +func isLowInBetween(low1, high1, low2, high2 int) bool { + if inBetweenInclusive(low1, low2, high2) || inBetweenInclusive(low2, low1, high1) { + return true + } + return false +} + +func isHighInBetween(low1, high1, low2, high2 int) bool { + if inBetweenInclusive(high1, low2, high2) || inBetweenInclusive(high2, low1, high1) { + return true + } + return false +}