
com.github.egateam.IntSpan Maven / Gradle / Ivy
Show all versions of jintspan Show documentation
/**
* IntSpan handles of sets containing integer spans.
*
* AUTHOR
* Qiang Wang, [email protected]
*
* COPYRIGHT AND LICENSE
* This software is copyright (c) 2016 by Qiang Wang.
*
* This is free software; you can redistribute it and/or modify it under the same terms as the Perl
* 5 programming language system itself.
*
* @author Qiang Wang
* @since 1.7
*/
package com.github.egateam;
import com.carrotsearch.hppc.IntArrayList;
import java.util.Arrays;
@SuppressWarnings("WeakerAccess")
public class IntSpan {
private static final String emptyString = "-";
// Real Largest int is posInf - 1
private static final int posInf = 2147483647 - 1; // INT_MAX - 1
private static final int negInf = -2147483648 + 1; // INT_MIN + 1
// TODO: Try HPPC
private IntArrayList edges = new IntArrayList();
//----------------------------------------------------------
// Constructors
//----------------------------------------------------------
/**
* Constructs an empty set.
*/
public IntSpan() {
}
/**
* Constructs a set with a single elements.
*
* @param val a valid integer
*/
public IntSpan(int val) {
addPair(val, val);
}
/**
* Constructs a set with a pair of integers constituting a range.
*
* @param lower lower boundary
* @param upper upper boundary ( upper must be larger than or equals to lower)
*/
public IntSpan(int lower, int upper) {
addPair(lower, upper);
}
/**
* Constructs a set with all elements in Array.
*
* @param ints integer array to add to this set
*/
public IntSpan(int[] ints) {
add(ints);
}
/**
* Constructs a copy set of the supplied set.
*
* @param supplied the supplied set
*/
public IntSpan(IntSpan supplied) {
edges = new IntArrayList(supplied.getEdges());
}
/**
* Constructs a set from the runlist string.
*
* @param runlist IntSpan string presentation
*/
public IntSpan(String runlist) {
add(runlist);
}
//----------------------------------------------------------
// Constants
//----------------------------------------------------------
/**
* Normally used in construction of infinite sets.
*
* @return positive infinity
*/
public static int getPosInf() {
return posInf - 1;
}
/**
* Normally used in construction of infinite sets.
*
* @return negative infinity
*/
public static int getNegInf() {
return negInf;
}
/**
* Useless in common cases.
*
* @return empty string "-"
*/
public static String getEmptyString() {
return emptyString;
}
//----------------------------------------------------------
// Set contents
//----------------------------------------------------------
/**
* Clear all elements of this set.
*
* @return this set for method chaining
*/
public IntSpan clear() {
edges = new IntArrayList();
return this;
}
/**
* Returns the internal used ArrayList representing the set.
*
* I don't think you should use this method.
*
* @return the internal used ArrayList representing this set
*/
private IntArrayList getEdges() {
return edges;
}
/**
* Returns the number of getEdges.
*
* @return the number of getEdges
*/
public int edgeSize() {
return edges.size();
}
/**
* Returns the number of spans.
*
* @return the number of spans
*/
public int spanSize() {
return edgeSize() / 2;
}
/**
* Returns a string representation of this set.
*
* @return a string representation of this set
*/
@Override
public String toString() {
if ( isEmpty() ) {
return emptyString;
}
String runlist = "";
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
String buf = "";
if ( i != 0 ) {
buf += ",";
}
if ( lower == upper ) {
buf += Integer.toString(lower);
} else {
buf += Integer.toString(lower) + "-" + Integer.toString(upper);
}
runlist += buf;
}
return runlist;
}
/**
* Returns an int[] containing all elements of this set in ascending order.
*
* @return an int[] containing all elements of this set in ascending order
*/
public int[] toArray() {
IntArrayList list = new IntArrayList();
if ( isEmpty() ) {
return list.toArray();
}
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
int spanSize = upper - lower + 1;
int[] spanElements = new int[spanSize];
for ( int j = 0; j < spanSize; j++ ) {
spanElements[j] = lower + j;
}
list.add(spanElements);
}
return list.toArray();
}
/**
* Returns the runs in this set, as a list of (lower, upper)
*
* @return the runs in this set, as a list of (lower, upper)
*/
public IntArrayList ranges() {
IntArrayList ranges = edges.clone();
for ( int i = 0; i < ranges.size(); i++ ) {
// odd index means upper
if ( (i & 1) == 1 ) {
ranges.set(i, ranges.get(i) - 1);
}
}
return ranges;
}
//----------------------------------------------------------
// Set cardinality
//----------------------------------------------------------
/**
* Returns the number of elements in this set.
*
* @return the number of elements in this set
*/
public int cardinality() {
int cardinality = 0;
if ( isEmpty() ) {
return cardinality;
}
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
cardinality += upper - lower + 1;
}
return cardinality;
}
/**
* Returns true if this set contains no elements.
*
* @return true if this set contains no elements
*/
public boolean isEmpty() {
return edgeSize() == 0;
}
/**
* Returns true if this set is not empty.
*
* @return true if this set is not empty
*/
public boolean isNotEmpty() {
return !isEmpty();
}
/**
* Returns true if this set is negative infinite.
*
* @return true if this set is negative infinite
*/
public boolean isNegInf() {
return edges.get(0) == negInf;
}
/**
* Returns true if this set is positive infinite.
*
* @return true if this set is positive infinite
*/
public boolean isPosInf() {
return edges.get(edges.size() - 1) == posInf;
}
/**
* Returns true if this set is infinite.
*
* @return true if this set is infinite
*/
public boolean isInfinite() {
return isNegInf() || isPosInf();
}
/**
* Returns true if this set is finite.
*
* @return true if this set is finite
*/
public boolean isFinite() {
return !isInfinite();
}
/**
* Returns true if this set contains all integers.
*
* @return true if this set contains all integers
*/
public boolean isUniversal() {
return edgeSize() == 2 && isNegInf() && isPosInf();
}
//----------------------------------------------------------
// Membership test
//----------------------------------------------------------
/**
* Returns true if this set contains all of the specified numbers.
*
* @param ints the specified numbers
* @return true if this set contains all of the specified numbers
*/
public boolean containsAll(int[] ints) {
for ( int i : ints ) {
int pos = findPos(i + 1, 0);
if ( (pos & 1) != 1 ) {
return false;
}
}
return true;
}
/**
* Returns true if this set contains the specified number.
*
* @param n the specified number
* @return true if this set contains the specified number
*/
public boolean contains(int n) {
int pos = findPos(n + 1, 0);
return (pos & 1) == 1;
}
/**
* Returns true if this set contains any of the specified numbers.
*
* @param ints the specified numbers
* @return true if this set contains any of the specified numbers
*/
public boolean containsAny(int[] ints) {
for ( int i : ints ) {
int pos = findPos(i + 1, 0);
if ( (pos & 1) == 1 ) {
return true;
}
}
return false;
}
//----------------------------------------------------------
// Member operations (mutate original set)
//----------------------------------------------------------
/**
* Adds a pair of inclusive integers to this set.
*
* A pair of integers constitute a range.
*
* @param lower lower boundary
* @param upper upper boundary ( upper must be larger than or equals to lower)
* @return this set for method chaining
*/
public IntSpan addPair(int lower, int upper) throws AssertionError {
upper++;
if ( lower > upper )
throw new AssertionError(String.format("Bad order: %s,%s", Integer.toString(lower), Integer.toString(upper)));
int lowerPos = findPos(lower, 0);
int upperPos = findPos(upper + 1, lowerPos);
if ( (lowerPos & 1) == 1 ) {
lower = edges.get(--lowerPos);
}
if ( (upperPos & 1) == 1 ) {
upper = edges.get(upperPos++);
}
edges.removeRange(lowerPos, upperPos);
edges.insert(lowerPos, lower);
edges.insert(lowerPos + 1, upper);
return this;
}
/**
* Adds the inclusive range of integers to this set.
*
* Multiple ranges may be specified. Each pair of integers constitute a range.
*
* @param ranges the inclusive ranges of integers (ranges.size() must be even)
* @return this set for method chaining
*/
public IntSpan addRange(IntArrayList ranges) throws AssertionError {
if ( ranges.size() % 2 != 0 ) throw new AssertionError("Number of ranges must be even");
// When this IntSpan is empty, just convert ranges to edges
if ( isEmpty() ) {
edges = ranges.clone();
for ( int i = 0; i < edges.size(); i++ ) {
// odd index means upper
if ( (i & 1) == 1 ) {
edges.set(i, edges.get(i) + 1);
}
}
} else {
edges.ensureCapacity(ranges.size());
for ( int i = 0; i < ranges.size() / 2; i++ ) {
int lower = ranges.get(i * 2);
int upper = ranges.get(i * 2 + 1);
addPair(lower, upper);
}
}
return this;
}
/**
* Merges the members of the supplied set into this set.
*
* @param supplied the supplied set
* @return this set for method chaining
*/
public IntSpan merge(IntSpan supplied) {
IntArrayList ranges = supplied.ranges();
addRange(ranges);
return this;
}
public IntSpan add(int n) {
addPair(n, n);
return this;
}
public IntSpan add(int[] array) {
IntArrayList ranges = listToRanges(array);
addRange(ranges);
return this;
}
public IntSpan add(IntSpan supplied) {
merge(supplied);
return this;
}
public IntSpan add(String runlist) {
// skip empty set
if ( !runlist.isEmpty() && !runlist.equals(emptyString) ) {
addRange(runlistToRanges(runlist));
}
return this;
}
/**
* Complement this set.
*
* Because our notion of infinity is actually disappointingly finite inverting a finite set
* results in another finite set. For example inverting the empty set makes it contain all the
* integers between negInf and posInf inclusive.
*
* As noted above negInf and posInf are actually just big integers.
*
* @return this set for method chaining
*/
public IntSpan invert() {
if ( isEmpty() ) {
// Universal set
edges = new IntArrayList();
edges.add(negInf, posInf);
} else {
// Either add or remove infinity from each end. The net effect is always an even number
// of additions and deletions
if ( isNegInf() ) {
edges.remove(0); // shift
} else {
edges.insert(0, negInf); // unshift
}
if ( isPosInf() ) {
edges.remove(edges.size() - 1); // pop
} else {
edges.add(posInf); // push
}
}
return this;
}
/**
* Removes a pair of inclusive integers from this set.
*
* @param lower lower boundary
* @param upper upper boundary ( upper must be larger than or equals to lower)
* @return this set for method chaining
*/
public IntSpan removePair(int lower, int upper) {
invert();
addPair(lower, upper);
invert();
return this;
}
/**
* Removes the inclusive range of integers from this set.
*
* Multiple ranges may be specified. Each pair of integers constitute a range.
*
* @param ranges the inclusive ranges of integers (ranges.size() must be even)
* @return this set for method chaining
*/
public IntSpan removeRange(IntArrayList ranges) throws AssertionError {
if ( ranges.size() % 2 != 0 ) throw new AssertionError("Number of ranges must be even");
invert();
addRange(ranges);
invert();
return this;
}
/**
* Subtracts the members of the supplied set out of this set.
*
* @param supplied the supplied set
* @return this set for method chaining
*/
public IntSpan subtract(IntSpan supplied) {
IntArrayList ranges = supplied.ranges();
removeRange(ranges);
return this;
}
public IntSpan remove(int n) {
removePair(n, n);
return this;
}
public IntSpan remove(int[] ints) {
IntArrayList ranges = listToRanges(ints);
removeRange(ranges);
return this;
}
public IntSpan remove(IntSpan supplied) {
subtract(supplied);
return this;
}
public IntSpan remove(String runlist) {
// empty set
if ( !runlist.isEmpty() && !runlist.equals(emptyString) ) {
removeRange(runlistToRanges(runlist));
}
return this;
}
//----------------------------------------------------------
// Set binary operations ( create new set)
//----------------------------------------------------------
/**
* Returns an identical copy of this IntSpan instance. The
* elements themselves are also preserved.
*
* @return a copy of this IntSpan instance
*/
public IntSpan copy() {
IntSpan newSet = new IntSpan();
newSet.edges = edges.clone();
return newSet;
}
/**
* Returns a new set that is the union (并集) of this set and the supplied set.
*
* @param supplied set to be operated with this set
* @return the union of this set and the supplied set
*/
public IntSpan union(IntSpan supplied) {
IntSpan newSet = copy();
newSet.merge(supplied);
return newSet;
}
/**
* Returns a new set that is the absolute complement (绝对补集) of this set.
*
* @return the absolute complement of this set
*/
public IntSpan complement() {
IntSpan newSet = copy();
newSet.invert();
return newSet;
}
/**
* Returns a new set that is the relative complement (相对补集) of the supplied set in this set.
* Also termed the set-theoretic difference of this set and the supplied set.
*
* In other words, the set of elements in this set, but not in the supplied set.
*
* @param supplied set to be operated with this set
* @return the relative complement of the supplied set in this set
*/
public IntSpan diff(IntSpan supplied) {
if ( isEmpty() ) {
return new IntSpan();
} else {
IntSpan newSet = copy();
newSet.subtract(supplied);
return newSet;
}
}
/**
* Returns a new set that is the intersection (交集) of this set and the supplied set.
*
* @param supplied set to be operated with this set
* @return the intersection of this set and the supplied set
*/
public IntSpan intersect(IntSpan supplied) {
if ( this.isEmpty() || supplied.isEmpty() ) {
return new IntSpan();
}
// when supplied IntSpan larger than this, swap
// no good effects
// if ( this.edgeSize() > supplied.edgeSize() ) {
// IntSpan newSet = complement();
// newSet.merge(supplied.complement());
// newSet.invert();
//
// return newSet;
// } else {
// IntSpan newSet = supplied.complement();
// newSet.merge(this.complement());
// newSet.invert();
//
// return newSet;
// }
IntSpan newSet = complement();
newSet.merge(supplied.complement());
newSet.invert();
return newSet;
}
/**
* Return a new set that contains all of the members that are in this set or the
* supplied set but not both.
*
* @param supplied set to be operated
* @return a new set that contains all of the members that are in this set or the supplied set
* but not both
*/
public IntSpan xor(IntSpan supplied) {
IntSpan newSet = union(supplied);
newSet.subtract(intersect(supplied));
return newSet;
}
//----------------------------------------------------------
// Set relations
//----------------------------------------------------------
/**
* Returns true if this set and the supplied set contain the same elements.
*
* @param supplied set to be compared
* @return true if this set and the supplied set contain the same elements
*/
public boolean equals(IntSpan supplied) {
IntArrayList edges_a = this.getEdges();
IntArrayList edges_b = supplied.getEdges();
if ( edges_a.size() != edges_b.size() ) {
return false;
}
for ( int i = 0; i < edges_a.size(); i++ ) {
int a = edges_a.get(i);
int b = edges_b.get(i);
if ( a != b ) {
return false;
}
}
return true;
}
/**
* Returns true if this set is a subset of the supplied set.
*
* @param supplied set to be compared
* @return true if this set is a subset of the supplied set
*/
public boolean subset(IntSpan supplied) {
return this.diff(supplied).isEmpty();
}
/**
* Returns true if this set is a superset of the supplied set.
*
* @param supplied set to be compared
* @return true if this set is a superset of the supplied set
*/
public boolean superset(IntSpan supplied) {
return supplied.diff(this).isEmpty();
}
//----------------------------------------------------------
// Extrema
//----------------------------------------------------------
/**
* Returns the smallest element of this set (can't be empty).
*
* @return the smallest element of this set
* @throws AssertionError for empty IntSpan
*/
public int min() throws AssertionError {
if ( !isNotEmpty() ) throw new AssertionError("Can't get extrema for empty IntSpan");
return edges.get(0);
}
/**
* Returns the largest element of this set (can't be empty).
*
* @return the largest element of this set
* @throws AssertionError for empty IntSpan
*/
public int max() throws AssertionError {
if ( !isNotEmpty() ) throw new AssertionError("Can't get extrema for empty IntSpan");
return edges.get(edges.size() - 1) - 1;
}
//----------------------------------------------------------
// Indexing
//----------------------------------------------------------
/**
* Returns the (index)th element of set, index start from "1".
*
* Negative indices count backwards from the end of the set.
*
* Index can't be "0".
*
* @param index index in this set
* @return the (index)th element of set
* @throws AssertionError for empty IntSpan and invalid index
*/
public int at(int index) throws AssertionError {
if ( isEmpty() ) throw new AssertionError("Indexing on an empty set");
if ( Math.abs(index) < 1 ) throw new AssertionError("Index start from 1");
if ( Math.abs(index) > cardinality() ) throw new AssertionError("Out of max index");
if ( index > 0 ) {
return atPos(index);
} else {
return atNeg(-index);
}
}
private int atPos(int index) {
int element = min();
int countOfElementsBefore = 0;
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
int thisSpanSize = upper - lower + 1;
if ( index > countOfElementsBefore + thisSpanSize ) {
countOfElementsBefore += thisSpanSize;
} else {
element = index - countOfElementsBefore - 1 + lower;
break;
}
}
return element;
}
private int atNeg(int index) {
int element = max();
int countOfElementsAfter = 0;
for ( int i = spanSize() - 1; i >= 0; i-- ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
int thisSpanSize = upper - lower + 1;
if ( index > countOfElementsAfter + thisSpanSize ) {
countOfElementsAfter += thisSpanSize;
} else {
element = upper - (index - countOfElementsAfter) + 1;
break;
}
}
return element;
}
/**
* Returns the index of an element in this set, index start from "1"
*
* @param element the element
* @return the index of an element in this set
* @throws AssertionError for empty IntSpan and invalid index
*/
public int index(int element) throws AssertionError {
if ( isEmpty() ) throw new AssertionError("Indexing on an empty set");
if ( !contains(element) ) throw new AssertionError("Element doesn't exist");
int index = -1; // not valid
int countOfElementsBefore = 0;
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
int thisSpanSize = upper - lower + 1;
if ( element >= lower && element <= upper ) {
index = element - lower + 1 + countOfElementsBefore;
} else {
countOfElementsBefore += thisSpanSize;
}
}
return index;
}
// TODO: slice()
//----------------------------------------------------------
// Spans operations
//----------------------------------------------------------
/**
* Returns a set consisting of a single span from set.min() to set.max().
*
* @return a set consisting of a single span from set.min() to set.max()
*/
public IntSpan cover() {
IntSpan newSet = new IntSpan();
if ( isNotEmpty() ) {
newSet.addPair(min(), max());
}
return newSet;
}
/**
* Returns a set containing all the holes in this set, that is, all the integers that are in-between
* spans of this set.
*
* @return a set containing all the holes in this set
*/
public IntSpan holes() {
IntSpan newSet = new IntSpan();
if ( isEmpty() || isUniversal() ) { // empty and universal set have no holes
return newSet;
} else {
IntSpan complementSet = complement();
IntArrayList ranges = complementSet.ranges();
// Remove infinite arms of complement set
if ( complementSet.isNegInf() ) {
ranges.remove(0);
ranges.remove(0);
}
if ( complementSet.isPosInf() ) {
ranges.remove(ranges.size() - 1);
ranges.remove(ranges.size() - 1);
}
newSet.addRange(ranges);
return newSet;
}
}
/**
* Returns a set constructed by removing n integers from each end of each span of this set. If
* n is negative, then -n integers are added to each end of each span.
*
* In the first case, spans may vanish from this set; in the second case, holes may vanish.
*
* @param n integer
* @return a set constructed by removing n integers from each end of each span of this set
*/
public IntSpan inset(int n) {
IntSpan newSet = new IntSpan();
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
if ( lower != getNegInf() ) {
lower += n;
}
if ( upper != getPosInf() ) {
upper -= n;
}
if ( lower <= upper ) {
newSet.addPair(lower, upper);
}
}
return newSet;
}
/**
* trim is provided as a synonym for inset.
*
* @param n integer
* @return a set
*/
public IntSpan trim(int n) {
return inset(n);
}
/**
* set.pad(n) is the same as set.inset(-n).
*
* @param n integer
* @return a set
*/
public IntSpan pad(int n) {
return inset(-n);
}
/**
* Removes all spans within this smaller than minLength
*
* @param minLength integer
* @return a new set
*/
public IntSpan excise(int minLength) {
IntSpan newSet = new IntSpan();
for ( int i = 0; i < spanSize(); i++ ) {
int lower = edges.get(i * 2);
int upper = edges.get(i * 2 + 1) - 1;
int thisSpanSize = upper - lower + 1;
if ( thisSpanSize >= minLength ) {
newSet.addPair(lower, upper);
}
}
return newSet;
}
/**
* Fills in all holes in this set smaller than or equals to maxLength
*
* @param maxLength integer
* @return a new set
*/
public IntSpan fill(int maxLength) {
IntSpan newSet = copy();
IntSpan holesSet = holes();
IntArrayList holesEdges = holesSet.getEdges();
for ( int i = 0; i < holesSet.spanSize(); i++ ) {
int lower = holesEdges.get(i * 2);
int upper = holesEdges.get(i * 2 + 1) - 1;
int thisSpanSize = upper - lower + 1;
if ( thisSpanSize <= maxLength ) {
newSet.addPair(lower, upper);
}
}
return newSet;
}
//----------------------------------------------------------
// TODO: Inter-set operations
//----------------------------------------------------------
//----------------------------------------------------------
// TODO: Islands
//----------------------------------------------------------
//----------------------------------------------------------
// Private methods
//----------------------------------------------------------
private static IntArrayList listToRanges(int[] ints) {
Arrays.sort(ints);
IntArrayList ranges = new IntArrayList();
int len = ints.length;
int pos = 0;
while ( pos < ints.length ) {
int end = pos + 1;
while ( (end < len) && (ints[end] <= ints[end - 1] + 1) ) {
end++;
}
ranges.add(ints[pos], ints[end - 1]);
pos = end;
}
return ranges;
}
private static IntArrayList runlistToRanges(String s) {
IntArrayList ranges = new IntArrayList();
int radix = 10;
int idx = 0; // index in runlist
int len = s.length();
boolean lowerNeg = false;
boolean upperNeg = false;
boolean inUpper = false;
while ( idx < len ) {
int i = 0; // index in one run
if ( s.charAt(idx) == '-' ) {
lowerNeg = true;
i++;
}
// Integer.parseInt() say this:
// Accumulating negatively avoids surprises near MAX_VALUE
int lower = 0, upper = 0;
for ( ; idx + i < len; i++ ) {
char ch = s.charAt(idx + i);
if ( ch >= '0' && ch <= '9' ) {
if ( !inUpper ) {
lower *= radix;
lower -= Character.digit(ch, radix);
} else {
upper *= radix;
upper -= Character.digit(ch, radix);
}
} else if ( ch == '-' && !inUpper ) {
inUpper = true;
if ( s.charAt(idx + i + 1) == '-' ) {
upperNeg = true;
}
} else if ( ch == ',' ) {
i++;
break; // end of run
}
}
if ( !inUpper ) {
ranges.add(lowerNeg ? lower : -lower); // add lower
ranges.add(lowerNeg ? lower : -lower); // add lower again
} else {
ranges.add(lowerNeg ? lower : -lower); // add lower
ranges.add(upperNeg ? upper : -upper); // add upper
}
// reset boolean flags
lowerNeg = false;
upperNeg = false;
inUpper = false;
// start next run
idx += i;
}
return ranges;
}
/**
* Return the index of the first element >= the supplied value.
*
* If the supplied value is larger than any element in the list the returned value will be equal
* to the size of the list.
*
* If (pos & 1) == 1, i.e. pos is odd number, val is in the set
*
* @param val supplied value
* @param low start value
* @return the index of the first element >= the supplied value.
*/
private int findPos(int val, int low) {
int high = edgeSize();
while ( low < high ) {
int mid = (low + high) / 2;
if ( val < edges.get(mid) ) {
high = mid;
} else if ( val > edges.get(mid) ) {
low = mid + 1;
} else {
return mid;
}
}
return low;
}
//----------------------------------------------------------
// Aliases
//----------------------------------------------------------
public int size() {
return cardinality();
}
public int count() {
return cardinality();
}
public String runlist() {
return toString();
}
public int[] elements() {
return toArray();
}
public boolean equal(IntSpan supplied) {
return equals(supplied);
}
public IntSpan intersection(IntSpan supplied) {
return intersect(supplied);
}
}