All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jlibs.core.util.Range Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/**
 * Copyright 2015 Santhosh Kumar Tekuri
 *
 * The JLibs authors license this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package jlibs.core.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * This class represents integer range.
 *
 * @author Santhosh Kumar T
 */
public class Range{
    public final int min;
    public final int max;

    /**
     * Note that both min and max are inclusive
     */
    public Range(int min, int max){
        if(min>max)
            throw new IllegalArgumentException("invalid range: ["+min+", "+max+']');
        this.min = min;
        this.max = max;
    }

    @Override
    public int hashCode(){
        return min+max;
    }

    @Override
    public boolean equals(Object obj){
        if(obj instanceof Range){
            Range that = (Range)obj;
            return this.min==that.min && this.max==that.max;
        }else
            return false;
    }

    @Override
    public String toString(){
        return "["+min+", "+max+']';
    }

    /**
     * return true if this range is before given number
     * 
     * ------------   o
     * 
*/ public boolean before(int x){ return x>max; } /** * returns true if this range is after given number *
     *   o   --------------
     * 
*/ public boolean after(int x){ return x * ------o-------- *
*/ public boolean contains(int x){ return !before(x) && !after(x); } /** * tells the position this range with respect to given range. *


* the return value is boolean array of size 3.
*

* 1st boolean ==> true if some portion of this range is before given range
* 2nd boolean ==> true if this range intersects with given range
* 3rd boolean ==> true if some portion of this range is after given range *
* ideally, you can remebers these boolean as { before, inside, after } */ public boolean[] position(Range that){ boolean before = that.after(min); boolean after = that.before(max); boolean inside; if(before && after) inside = true; else if(!before && !after) inside = true; else if(before) inside = that.contains(max); else inside = that.contains(min); return new boolean[]{ before, inside, after }; } /** * this method splits this range into 3 regions with respect to given range *


* the return value is Range array of size 3.
*

* 1st range ==> the portion of this range that is before given range
* 2nd range ==> the portion of range that is common to this range and given range
* 3rd range ==> the portion of this range that is after given range. *
* Note that the values in returned array can be null, if there is no range satifying * the requirement. */ public Range[] split(Range that){ boolean position[] = position(that); Range before = null; if(position[0]) before = new Range(this.min, Math.min(this.max, that.min-1)); Range after = null; if(position[2]) after = new Range(Math.max(this.min, that.max+1), this.max); Range inside = null; if(position[1]) inside = new Range(Math.max(this.min, that.min), Math.min(this.max, that.max)); return new Range[]{ before, inside, after }; } /** * return the portion of range that is common to this range and given range.
* If there is nothing common, then null is returned. */ public Range intersection(Range that){ return split(that)[1]; } /** * returns union of this range with given range.
* if both ranges are adjacent/intersecting to each other, then the * returned array will have only one range. otherwise the returned array * will have two ranges in sorted order. */ public Range[] union(Range that){ if(this.min>that.min) return that.union(this); // this ------------- // that -------------- // that ------- if(contains(that.min)) return new Range[]{ new Range(this.min, Math.max(this.max, that.max)) }; // this ----------- // that -------------- return new Range[]{ this, that }; } /** * returns the portion(s) of this range that are not present in given range. * maximum size of returned array is 2. and the array is sorted. */ public Range[] minus(Range that){ Range split[] = split(that); if(split[0]==null && split[2]==null) return new Range[0]; if(split[0]!=null && split[2]!=null) return new Range[]{ split[0], split[2] }; return new Range[]{ split[0]!=null ? split[0] : split[2] }; } /*-------------------------------------------------[ Helpers ]---------------------------------------------------*/ public static List union(List ranges){ ranges = new ArrayList(ranges); Collections.sort(ranges, new Comparator(){ @Override public int compare(Range r1, Range r2){ return r1.min-r2.min; } }); List union = new ArrayList(); for(Range r: ranges){ if(union.isEmpty()) union.add(r); else CollectionUtil.addAll(union, union.remove(union.size() - 1).union(r)); } return union; } public static List intersection(List list1, List list2){ list1 = union(list1); list2 = union(list2); List intersection = new ArrayList(); for(Range r1: list1){ for(Range r2: list2){ Range r = r1.intersection(r2); if(r!=null) intersection.add(r); } } return union(intersection); } public static List minus(List list1, List list2){ list1 = union(list1); list2 = union(list2); for(Range r2: list2){ List temp = new ArrayList(); for(Range r1: list1) CollectionUtil.addAll(temp, r1.minus(r2)); list1 = temp; } return union(list1); } public static boolean same(List list1, List list2){ list1 = union(list1); list2 = union(list2); return list1.equals(list2); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy