Task: Range consolidation




Go: package main

import (
    "fmt"
    "math"
    "sort"
)

type Range struct{ Lower, Upper float64 }

func (r Range) Norm() Range {
    if r.Lower > r.Upper {
        return Range{r.Upper, r.Lower}
    }
    return r
}

func (r Range) String() string {
    return fmt.Sprintf("[%g, %g]", r.Lower, r.Upper)
}

func (r1 Range) Union(r2 Range) []Range {
    if r1.Upper < r2.Lower {
        return []Range{r1, r2}
    }
    r := Range{r1.Lower, math.Max(r1.Upper, r2.Upper)}
    return []Range{r}
}

func consolidate(rs []Range) []Range {
    for i := range rs {
        rs[i] = rs[i].Norm()
    }
    le := len(rs)
    if le < 2 {
        return rs
    }
    sort.Slice(rs, func(i, j int) bool {
        return rs[i].Lower < rs[j].Lower
    })
    if le == 2 {
        return rs[0].Union(rs[1])
    }
    for i := 0; i < le-1; i++ {
        for j := i + 1; j < le; j++ {
            ru := rs[i].Union(rs[j])
            if len(ru) == 1 {
                rs[i] = ru[0]
                copy(rs[j:], rs[j+1:])
                rs = rs[:le-1]
                le--
                i--
                break
            }
        }
    }
    return rs
}

func main() {
    rss := [][]Range{
        {{1.1, 2.2}},
        {{6.1, 7.2}, {7.2, 8.3}},
        {{4, 3}, {2, 1}},
        {{4, 3}, {2, 1}, {-1, -2}, {3.9, 10}},
        {{1, 3}, {-6, -1}, {-4, -5}, {8, 2}, {-6, -6}},
    }
    for _, rs := range rss {
        s := fmt.Sprintf("%v", rs)
        fmt.Printf("%40s => ", s[1:len(s)-1])
        rs2 := consolidate(rs)
        s = fmt.Sprintf("%v", rs2)
        fmt.Println(s[1 : len(s)-1])
    }
}


Java: import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class RangeConsolidation {

    public static void main(String[] args) {
        displayRanges( Arrays.asList(new Range(1.1, 2.2)));
        displayRanges( Arrays.asList(new Range(6.1, 7.2), new Range(7.2, 8.3)));
        displayRanges( Arrays.asList(new Range(4, 3), new Range(2, 1)));
        displayRanges( Arrays.asList(new Range(4, 3), new Range(2, 1), new Range(-1, -2), new Range(3.9, 10)));
        displayRanges( Arrays.asList(new Range(1, 3), new Range(-6, -1), new Range(-4, -5), new Range(8, 2), new Range(-6, -6)));
        displayRanges( Arrays.asList(new Range(1, 1), new Range(1, 1)));
        displayRanges( Arrays.asList(new Range(1, 1), new Range(1, 2)));
        displayRanges( Arrays.asList(new Range(1, 2), new Range(3, 4), new Range(1.5, 3.5), new Range(1.2, 2.5)));
    }
    
    private static final void displayRanges(List<Range> ranges) {
        System.out.printf("ranges = %-70s, colsolidated = %s%n", ranges, Range.consolidate(ranges));
    }
    
    private static final class RangeSorter implements Comparator<Range> {
        @Override
        public int compare(Range o1, Range o2) {
            return (int) (o1.left - o2.left);
        }        
    }

    private static class Range {
        double left;
        double right;
        
        public Range(double left, double right) {
            if ( left <= right ) {
                this.left = left;
                this.right = right;
            }
            else {
                this.left = right;
                this.right = left;
            }
        }
        
        public Range consolidate(Range range) {
            
            if ( this.right < range.left ) {
                return null;
            }
            
            if ( range.right < this.left ) {
                return null;
            }
            
            if ( this.left <= range.left && this.right >= range.right ) {
                return this;
            }
            
            if ( range.left <= this.left && range.right >= this.right ) {
                return range;
            }
            
            if ( this.left <= range.left && this.right <= range.right ) {
                return new Range(this.left, range.right);
            }
            
            if ( this.left >= range.left && this.right >= range.right ) {
                return new Range(range.left, this.right);
            }
            throw new RuntimeException("ERROR:  Logic invalid.");
        }
        
        @Override
        public String toString() {
            return "[" + left + ", " + right + "]";
        }
        
        private static List<Range> consolidate(List<Range> ranges) {
            List<Range> consolidated = new ArrayList<>();
            
            Collections.sort(ranges, new RangeSorter());
            
            for ( Range inRange : ranges ) {
                Range r = null;
                Range conRange = null;
                for ( Range conRangeLoop : consolidated ) {
                    r = inRange.consolidate(conRangeLoop);
                    if (r != null ) {
                        conRange = conRangeLoop;
                        break;
                    }
                }
                if ( r == null ) {
                    consolidated.add(inRange);
                }
                else {
                    consolidated.remove(conRange);
                    consolidated.add(r);                    
                }
            }
            
            Collections.sort(consolidated, new RangeSorter());
            
            return consolidated;
        }
    }

}