// If you edit this file, you must also edit its tests.
// For tests of this and the entire plume package, see class TestPlume.
package plume;
import java.util.*;
/**
* Utilities for manipulating arrays and collections.
* This complements {@link java.util.Arrays} and {@link java.util.Collections}.
**/
@SuppressWarnings("interning")
public final class ArraysMDE {
private ArraysMDE() { throw new Error("do not instantiate"); }
///////////////////////////////////////////////////////////////////////////
/// min, max
///
// Could also add linear-time orderStatistics if I liked.
/**
* Return the smallest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static int min(int[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to min(int[])");
int result = a[0];
for (int i=1; i<a.length; i++)
result = Math.min(result, a[i]);
return result;
}
/**
* Return the smallest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static long min(long[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to min(long[])");
long result = a[0];
for (int i=1; i<a.length; i++)
result = Math.min(result, a[i]);
return result;
}
/**
* Return the smallest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static double min(double[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to min(double[])");
double result = a[0];
for (int i=1; i<a.length; i++)
result = Math.min(result, a[i]);
return result;
}
/**
* Return the smallest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static Integer min(Integer[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to min(Integer[])");
Integer result = a[0]; // to return a value actually in the array
int result_int = result.intValue(); // for faster comparison
for (int i=1; i<a.length; i++) {
if (a[i].intValue() < result_int) {
result = a[i];
result_int = result.intValue();
}
}
return result;
}
/**
* Return the smallest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static Long min(Long[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to min(Long[])");
Long result = a[0]; // to return a value actually in the array
long result_long = result.longValue(); // for faster comparison
for (int i=1; i<a.length; i++) {
if (a[i].longValue() < result_long) {
result = a[i];
result_long = result.longValue();
}
}
return result;
}
/**
* Return the smallest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static Double min(Double[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to min(Double[])");
Double result = a[0]; // to return a value actually in the array
int result_int = result.intValue(); // for faster comparison
for (int i=1; i<a.length; i++) {
if (a[i].intValue() < result_int) {
result = a[i];
result_int = result.intValue();
}
}
return result;
}
/**
* Return the largest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static int max(int[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to max(int[])");
int result = a[0];
for (int i=1; i<a.length; i++)
result = Math.max(result, a[i]);
return result;
}
/**
* Return the largest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static long max(long[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to max(long[])");
long result = a[0];
for (int i=1; i<a.length; i++)
result = Math.max(result, a[i]);
return result;
}
/**
* Return the largest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static double max(double[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to max(double[])");
double result = a[0];
for (int i=1; i<a.length; i++)
result = Math.max(result, a[i]);
return result;
}
/**
* Return the largest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static Integer max(Integer[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to max(Integer[])");
Integer result = a[0]; // to return a value actually in the array
int result_int = result.intValue(); // for faster comparison
for (int i=1; i<a.length; i++) {
if (a[i].intValue() > result_int) {
result = a[i];
result_int = result.intValue();
}
}
return result;
}
/**
* Return the largest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static Long max(Long[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to max(Long[])");
Long result = a[0]; // to return a value actually in the array
long result_long = result.longValue(); // for faster comparison
for (int i=1; i<a.length; i++) {
if (a[i].longValue() > result_long) {
result = a[i];
result_long = result.longValue();
}
}
return result;
}
/**
* Return the largest value in the array.
* @throws ArrayIndexOutOfBoundsException if the array has length 0
**/
public static Double max(Double[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to max(Double[])");
Double result = a[0]; // to return a value actually in the array
int result_int = result.intValue(); // for faster comparison
for (int i=1; i<a.length; i++) {
if (a[i].intValue() > result_int) {
result = a[i];
result_int = result.intValue();
}
}
return result;
}
/**
* Return a two-element array containing the smallest and largest values in the array.
* Throw ArrayIndexOutOfBoundsException if the array has length 0.
**/
public static int [] min_max(int[] a) {
if (a.length == 0) {
// return null;
throw new ArrayIndexOutOfBoundsException("Empty array passed to min_max(int[])");
}
int result_min = a[0];
int result_max = a[0];
for (int i=1; i<a.length; i++) {
result_min = Math.min(result_min, a[i]);
result_max = Math.max(result_max, a[i]);
}
return new int[] { result_min, result_max };
}
/**
* Return a two-element array containing the smallest and largest values in the array.
* Throw ArrayIndexOutOfBoundsException if the array has length 0.
**/
public static long [] min_max(long[] a) {
if (a.length == 0) {
// return null;
throw new ArrayIndexOutOfBoundsException("Empty array passed to min_max(long[])");
}
long result_min = a[0];
long result_max = a[0];
for (int i=1; i<a.length; i++) {
result_min = Math.min(result_min, a[i]);
result_max = Math.max(result_max, a[i]);
}
return new long[] { result_min, result_max };
}
/**
* Return the difference between the smallest and largest array elements.
**/
public static int element_range(int[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to element_range(int[])");
int [] min_max = min_max(a);
return min_max[1] - min_max[0];
}
/**
* Return the difference between the smallest and largest array elements.
**/
public static long element_range(long[] a) {
if (a.length == 0)
throw new ArrayIndexOutOfBoundsException("Empty array passed to element_range(long[])");
long [] min_max = min_max(a);
return min_max[1] - min_max[0];
}
// Returns the sum of an array of integers
public static int sum(int[] a) {
int sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
// Returns the sum of all the elements of a 2d array of integers
public static int sum(int[][] a) {
int sum = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
sum += a[i][j];
}
}
return sum;
}
// Returns the sum of an array of integers
public static double sum(double[] a) {
double sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
// Returns the sum of all the elements of a 2d array of integers
public static double sum(double[][] a) {
double sum = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
sum += a[i][j];
}
}
return sum;
}
///////////////////////////////////////////////////////////////////////////
/// indexOf
///
/**
* Searches for the first occurrence of the given element in the array,
* testing for equality using the equals method.
* @return the first index whose element is equal to the specified element,
* or -1 if no such element is found in the array.
* @see java.util.List#indexOf(java.lang.Object)
**/
public static <T> int indexOf(T[] a, /*@Nullable*/ Object elt) {
if (elt == null) {
return indexOfEq(a, elt);
}
for (int i=0; i<a.length; i++)
if (elt.equals(a[i]))
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array,
* testing for equality using the equals method.
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in that section of the array.
* @see java.util.List#indexOf(java.lang.Object)
**/
public static <T> int indexOf(T[] a, /*@Nullable*/ Object elt, int minindex, int indexlimit) {
if (elt == null) {
return indexOfEq(a, elt, minindex, indexlimit);
}
for (int i=minindex; i<indexlimit; i++)
if (elt.equals(a[i]))
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the list,
* testing for equality using the equals method.
* Identical to List.indexOf, but included for completeness.
* @return the first index whose element is equal to the specified element,
* or -1 if no such element is found in the list.
* @see java.util.List#indexOf(java.lang.Object)
**/
public static int indexOf(List<? extends /*@PolyNull*/ Object> a, /*@Nullable*/ Object elt) {
return a.indexOf(elt);
}
/**
* Searches for the first occurrence of the given element in the list,
* testing for equality using the equals method.
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in that section of the list.
* @see java.util.List#indexOf(java.lang.Object)
**/
public static int indexOf(List<? extends /*@PolyNull*/ Object> a, /*@Nullable*/ Object elt, int minindex, int indexlimit) {
if (elt == null) {
return indexOfEq(a, elt, minindex, indexlimit);
}
for (int i=minindex; i<indexlimit; i++)
if (elt.equals(a.get(i)))
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array,
* testing for equality using == (not the equals method).
* @return the first index containing the specified element,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOfEq(/*@PolyNull*/ Object[] a, /*@Nullable*/ Object elt) {
for (int i=0; i<a.length; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array,
* testing for equality using == (not the equals method).
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in that section of the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOfEq(/*@PolyNull*/ Object[] a, /*@Nullable*/ Object elt, int minindex, int indexlimit) {
for (int i=minindex; i<indexlimit; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the list,
* testing for equality using == (not the equals method).
* @return the first index containing the specified element,
* or -1 if the element is not found in the list.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOfEq(List<? extends /*@PolyNull*/ Object> a, /*@Nullable*/ Object elt) {
for (int i=0; i<a.size(); i++)
if (elt == a.get(i))
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the list,
* testing for equality using == (not the equals method).
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in that section of the list.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOfEq(List<? extends /*@PolyNull*/ Object> a, /*@Nullable*/ Object elt, int minindex, int indexlimit) {
for (int i=minindex; i<indexlimit; i++)
if (elt == a.get(i))
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index containing the specified element,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(int[] a, int elt) {
for (int i=0; i<a.length; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index containing the specified element,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(long[] a, long elt) {
for (int i=0; i<a.length; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(int[] a, int elt, int minindex, int indexlimit) {
for (int i=minindex; i<indexlimit; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(long[] a, long elt, int minindex, int indexlimit) {
for (int i=minindex; i<indexlimit; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index containing the specified element,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(boolean[] a, boolean elt) {
for (int i=0; i<a.length; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index containing the specified element,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(double[] a, double elt) {
for (int i=0; i<a.length; i++)
if (elt == a[i])
return i;
return -1;
}
/**
* Searches for the first occurrence of the given element in the array.
* @return the first index i containing the specified element,
* such that minindex <= i < indexlimit,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
**/
public static int indexOf(boolean[] a, boolean elt, int minindex, int indexlimit) {
for (int i=minindex; i<indexlimit; i++)
if (elt == a[i])
return i;
return -1;
}
///////////////////////////////////////////////////////////////////////////
/// indexOf, for finding subarrays
///
// This is analogous to Common Lisp's "search" function.
// This implementation is very inefficient; I could use tricky Boyer-Moore
// search techniques if I liked, but it's not worth it to me yet.
/**
* Searches for the first subsequence of the array that matches the given array elementwise,
* testing for equality using the equals method.
* @return the first index at which the second array starts in the first array,
* or -1 if no such element is found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(Object[] a, Object[] sub) {
int a_index_max = a.length - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given array elementwise,
* testing for equality using == (not the equals method).
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOfEq(Object[] a, Object[] sub) {
int a_index_max = a.length - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarrayEq(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the list that matches the given array elementwise,
* testing for equality using the equals method.
* @return the first index at which the second array starts in the first list,
* or -1 if no such element is found in the list.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(List<?> a, Object[] sub) {
int a_index_max = a.size() - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the list that matches the given array elementwise,
* testing for equality using == (not the equals method).
* @return the first index at which the second array starts in the first list,
* or -1 if the element is not found in the list.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOfEq(List<?> a, Object[] sub) {
int a_index_max = a.size() - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarrayEq(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given list elementwise,
* testing for equality using the equals method.
* @return the first index at which the second list starts in the first array,
* or -1 if no such element is found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(Object[] a, List<?> sub) {
int a_index_max = a.length - sub.size() + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given list elementwise,
* testing for equality using == (not the equals method).
* @return the first index at which the second list starts in the first array,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOfEq(Object[] a, List<?> sub) {
int a_index_max = a.length - sub.size() + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarrayEq(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the list that matches the given list elementwise,
* testing for equality using the equals method.
* @return the first index at which the second list starts in the first list,
* or -1 if no such element is found in the list.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(List<?> a, List<?> sub) {
int a_index_max = a.size() - sub.size() + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the list that matches the given list elementwise,
* testing for equality using == (not the equals method).
* @return the first index at which the second list starts in the first list,
* or -1 if the element is not found in the list.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOfEq(List<?> a, List<?> sub) {
int a_index_max = a.size() - sub.size() + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarrayEq(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given array elementwise.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(int[] a, int[] sub) {
int a_index_max = a.length - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given array elementwise.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(double[] a, double[] sub) {
int a_index_max = a.length - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given array elementwise.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(long[] a, long[] sub) {
int a_index_max = a.length - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
/**
* Searches for the first subsequence of the array that matches the given array elementwise.
* @return the first index containing the specified element,
* or -1 if the element is not found in the array.
* @see java.util.Vector#indexOf(java.lang.Object)
* @see java.lang.String#indexOf(java.lang.String)
**/
public static int indexOf(boolean[] a, boolean[] sub) {
int a_index_max = a.length - sub.length + 1;
for (int i=0; i<=a_index_max; i++)
if (isSubarray(a, sub, i))
return i;
return -1;
}
///////////////////////////////////////////////////////////////////////////
/// mismatch
///
// This is analogous to Common Lisp's "mismatch" function.
// Put it off until later; for now, use the simpler subarray function,
// which is a specialization of mismatch,
///////////////////////////////////////////////////////////////////////////
/// subarray extraction
///
// Note that the second argument is a length, not an end position.
// That's to avoid confusion over whether it would be the last included
// index or the first non-included index.
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static /*@PolyNull*/ /*@PolyInterned*/ Object[] subarray(/*@PolyNull*/ /*@PolyInterned*/ Object[] a, int startindex, int length) {
/*@PolyNull*/ /*@PolyInterned*/ Object[] result = new /*@PolyNull*/ /*@PolyInterned*/ Object[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a sublist of the given list.
* @param a the original list
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static <T> List<T> subarray(List<T> a, int startindex, int length) {
return a.subList(startindex, startindex+length);
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static /*@PolyNull*/ /*@PolyInterned*/ String[] subarray(/*@PolyNull*/ /*@PolyInterned*/ String[] a, int startindex, int length) {
/*@PolyNull*/ /*@PolyInterned*/ String[] result = new String[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static byte[] subarray(byte[] a, int startindex, int length) {
byte[] result = new byte[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static boolean[] subarray(boolean[] a, int startindex, int length) {
boolean[] result = new boolean[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static char[] subarray(char[] a, int startindex, int length) {
char[] result = new char[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static double[] subarray(double[] a, int startindex, int length) {
double[] result = new double[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static float[] subarray(float[] a, int startindex, int length) {
float[] result = new float[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static int[] subarray(int[] a, int startindex, int length) {
int[] result = new int[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static long[] subarray(long[] a, int startindex, int length) {
long[] result = new long[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
/**
* Return a subarray of the given array.
* @param a the original array
* @param startindex the first index to be included
* @param length the number of elements to include (not an end index,
* to avoid confusion over whether it would be the last included
* index or the first non-included index)
**/
public static short[] subarray(short[] a, int startindex, int length) {
short[] result = new short[length];
System.arraycopy(a, startindex, result, 0, length);
return result;
}
///////////////////////////////////////////////////////////////////////////
/// subarray testing
///
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using the equals method.
* @return the first index at which the second array starts in the first array,
* or -1 if no such element is found in the array.
**/
public static boolean isSubarray(Object[] a, Object[] sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (! sub[i].equals(a[a_offset+i]))
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using == (not the equals method).
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarrayEq(Object[] a, Object[] sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub[i] != a[a_offset+i])
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using the equals method.
* @return the first index at which the second array starts in the first array,
* or -1 if no such element is found in the array.
**/
public static boolean isSubarray(Object[] a, List<?> sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.size();
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (! sub.get(i).equals(a[a_offset+i]))
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using == (not the equals method).
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarrayEq(Object[] a, List<?> sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.size();
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub.get(i) != a[a_offset+i])
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using the equals method.
* @return the first index at which the second array starts in the first array,
* or -1 if no such element is found in the array.
**/
public static boolean isSubarray(List<?> a, Object[] sub, int a_offset) {
int a_len = a.size() - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (! sub[i].equals(a.get(a_offset+i)))
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using == (not the equals method).
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarrayEq(List<?> a, Object[] sub, int a_offset) {
int a_len = a.size() - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub[i] != a.get(a_offset+i))
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using the equals method.
* @return the first index at which the second array starts in the first array,
* or -1 if no such element is found in the array.
**/
public static boolean isSubarray(List<?> a, List<?> sub, int a_offset) {
int a_len = a.size() - a_offset;
int sub_len = sub.size();
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (! sub.get(i).equals(a.get(a_offset+i)))
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first,
* testing for equality using == (not the equals method).
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarrayEq(List<?> a, List<?> sub, int a_offset) {
int a_len = a.size() - a_offset;
int sub_len = sub.size();
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub.get(i) != a.get(a_offset+i))
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarray(int[] a, int[] sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub[i] != a[a_offset+i])
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarray(long[] a, long[] sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub[i] != a[a_offset+i])
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarray(double[] a, double[] sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub[i] != a[a_offset+i])
return false;
return true;
}
/**
* Determines whether the second array is a subarray of the first,
* starting at the specified index of the first.
* @return the first index at which the second array starts in the first array,
* or -1 if the element is not found in the array.
**/
public static boolean isSubarray(boolean[] a, boolean[] sub, int a_offset) {
int a_len = a.length - a_offset;
int sub_len = sub.length;
if (a_len < sub_len)
return false;
for (int i=0; i<sub_len; i++)
if (sub[i] != a[a_offset+i])
return false;
return true;
}
///////////////////////////////////////////////////////////////////////////
/// concatenation
///
// Concat used to return null if both arguments are null. That is
// convenient for the implementer, but not so good for clients.
// Exists to suppress warnings
private static <T> T[] toTArray(List<T> lst) {
@SuppressWarnings("unchecked")
T[] asArray = (T[]) lst.toArray();
return asArray;
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static <T> T[] concat(T /*@Nullable*/ [] a, T /*@Nullable*/ [] b) {
if (a == null) {
if (b != null) {
return b;
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[0];
return result;
}
} else {
if (b == null) {
return a;
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static <T> T[] concat(T /*@Nullable*/ [] a, /*@Nullable*/ List<T> b) {
if (a == null) {
if (b != null) {
return toTArray(b);
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[0];
return result;
}
} else {
if (b == null) {
return a;
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[a.length + b.size()];
System.arraycopy(a, 0, result, 0, a.length);
// System.arraycopy(b, 0, result, a.length, b.size());
for (int i=0; i<b.size(); i++) {
result[i+a.length] = b.get(i);
}
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static <T> T[] concat(/*@Nullable*/ List<T> a, T /*@Nullable*/ [] b) {
if (a == null) {
if (b != null) {
return b;
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[0];
return result;
}
} else {
if (b == null) {
return toTArray(a);
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[a.size() + b.length];
// System.arraycopy(a, 0, result, 0, a.size());
for (int i=0; i<a.size(); i++) {
result[i] = a.get(i);
}
System.arraycopy(b, 0, result, a.size(), b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static <T> T[] concat(/*@Nullable*/ List<T> a, /*@Nullable*/ List<T> b) {
if (a == null) {
if (b != null) {
return toTArray(b);
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[0];
return result;
}
} else {
if (b == null) {
return toTArray(a);
} else {
@SuppressWarnings("unchecked")
T[] result = (T[]) new Object[a.size() + b.size()];
// System.arraycopy(a, 0, result, 0, a.length);
for (int i=0; i<a.size(); i++) {
result[i] = a.get(i);
}
// System.arraycopy(b, 0, result, a.length, b.length);
for (int i=0; i<b.size(); i++) {
result[i+a.size()] = b.get(i);
}
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static String[] concat(String /*@Nullable*/ [] a, String /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new String[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
String[] result = new String[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static byte[] concat(byte /*@Nullable*/ [] a, byte /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new byte[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
byte[] result = new byte[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static boolean[] concat(boolean /*@Nullable*/ [] a, boolean /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new boolean[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
boolean[] result = new boolean[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static char[] concat(char /*@Nullable*/ [] a, char /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new char[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
char[] result = new char[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static double[] concat(double /*@Nullable*/ [] a, double /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new double[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
double[] result = new double[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static float[] concat(float /*@Nullable*/ [] a, float /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new float[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
float[] result = new float[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static int[] concat(int /*@Nullable*/ [] a, int /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new int[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
int[] result = new int[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static long[] concat(long /*@Nullable*/ [] a, long /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new long[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
long[] result = new long[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
/**
* Return an array that contains all the elements of both argument
* arrays, in order.
* Returns a new array unless one argument is null, in which case
* it returns the other array.
**/
public static short[] concat(short /*@Nullable*/ [] a, short /*@Nullable*/ [] b) {
if (a == null) {
if (b == null) {
return new short[0];
} else {
return b;
}
} else {
if (b == null) {
return a;
} else {
short[] result = new short[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
}
///////////////////////////////////////////////////////////////////////////
/// Printing
///
// This should be extended to all types, when I get around to it. The
// methods are patterned after that of java.util.Vector (and use its
// output format).
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(Object /*@Nullable*/ [] a) {
return toString(a, false);
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* Furthermore, each element is quoted like a Java String.
* @see java.util.Vector#toString
**/
public static String toStringQuoted(Object /*@Nullable*/ [] a) {
return toString(a, true);
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* Furthermore, if quoted is true, then each element is quoted like a Java String.
* @see java.util.Vector#toString
**/
public static String toString(Object /*@Nullable*/ [] a, boolean quoted) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.length > 0) {
sb.append(a[0]);
for (int i=1; i<a.length; i++) {
sb.append(", ");
if (quoted) {
sb.append('\"');
sb.append(UtilMDE.escapeNonJava((String)a[i]));
sb.append('\"');
} else {
sb.append(a[i]);
}
}
}
sb.append("]");
return sb.toString();
}
// Why don't the next 3 classes take an arbitrary collection?
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(/*@Nullable*/ List<?> a) {
return toString(a, false);
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toStringQuoted(/*@Nullable*/ List<?> a) {
return toString(a, true);
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(/*@Nullable*/ List<?> a, boolean quoted) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.size() > 0) {
sb.append(a.get(0));
for (int i=1; i<a.size(); i++) {
sb.append(", ");
if (quoted) {
sb.append('\"');
sb.append(UtilMDE.escapeNonJava((String)a.get(i)));
sb.append('\"');
} else {
sb.append(a.get(i));
}
}
}
sb.append("]");
return sb.toString();
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(int[] a) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.length > 0) {
sb.append(a[0]);
for (int i=1; i<a.length; i++) {
sb.append(", ");
sb.append(a[i]);
}
}
sb.append("]");
return sb.toString();
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(long[] a) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.length > 0) {
sb.append(a[0]);
for (int i=1; i<a.length; i++) {
sb.append(", ");
sb.append(a[i]);
}
}
sb.append("]");
return sb.toString();
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(double[] a) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.length > 0) {
sb.append(a[0]);
for (int i=1; i<a.length; i++) {
sb.append(", ");
sb.append(a[i]);
}
}
sb.append("]");
return sb.toString();
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(float[] a) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.length > 0) {
sb.append(a[0]);
for (int i=1; i<a.length; i++) {
sb.append(", ");
sb.append(a[i]);
}
}
sb.append("]");
return sb.toString();
}
/**
* Return a string representation of the array.
* The representation is patterned after that of java.util.Vector.
* @see java.util.Vector#toString
**/
public static String toString(boolean[] a) {
if (a == null) {
return "null";
}
StringBuffer sb = new StringBuffer();
sb.append("[");
if (a.length > 0) {
sb.append(a[0]);
for (int i=1; i<a.length; i++) {
sb.append(", ");
sb.append(a[i]);
}
}
sb.append("]");
return sb.toString();
}
/**
* Casts obj down to the proper array type then calls the appropriate
* toString() method. Only call this method if obj is a boolean, double,
* int, long, or Object array.
* @throws IllegalArgumentException if obj is null or is not one of the types mentioned above.
*/
public static String toString(Object obj) throws IllegalArgumentException {
if (obj instanceof boolean[]) {
return toString((boolean[]) obj);
} else if (obj instanceof double[]) {
return toString((double[]) obj);
} else if (obj instanceof float[]) {
return toString((float[]) obj);
} else if (obj instanceof int[]) {
return toString((int[]) obj);
} else if (obj instanceof long[]) {
return toString((long[]) obj);
} else if (obj instanceof Object[]) {
return toString((Object[]) obj);
} else if (obj instanceof List<?>) {
return toString((List<?>) obj);
} else {
throw new IllegalArgumentException("Argument is " + ((obj == null) ? "null" :
"of class " + obj.getClass().getName()));
}
}
/**
* Casts obj down to the proper array type then calls .length.
* Only call this method if obj is a boolean, double, int, long, or Object array.
* @throws IllegalArgumentException if obj is null or is not one of the types mentioned above.
*/
public static int length(Object obj) throws IllegalArgumentException {
if (obj instanceof boolean[]) {
return ((boolean[]) obj).length;
} else if (obj instanceof double[]) {
return ((double[]) obj).length;
} else if (obj instanceof int[]) {
return ((int[]) obj).length;
} else if (obj instanceof long[]) {
return ((long[]) obj).length;
} else if (obj instanceof Object[]) {
return ((Object[]) obj).length;
} else if (obj instanceof List<?>) {
return ((List<?>) obj).size();
} else {
throw new IllegalArgumentException("Argument is " + ((obj == null) ? "null" :
"of class " + obj.getClass().getName()));
}
}
///////////////////////////////////////////////////////////////////////////
/// Sortedness
///
public static boolean sorted(int[] a) {
for (int i=0; i<a.length-1; i++)
if (a[i+1] < a[i])
return false;
return true;
}
public static boolean sorted(long[] a) {
for (int i=0; i<a.length-1; i++)
if (a[i+1] < a[i])
return false;
return true;
}
public static boolean sorted_descending(int[] a) {
for (int i=0; i<a.length-1; i++)
if (a[i+1] > a[i])
return false;
return true;
}
public static boolean sorted_descending(long[] a) {
for (int i=0; i<a.length-1; i++)
if (a[i+1] > a[i])
return false;
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (boolean[] a) {
HashSet<Boolean> hs = new HashSet<Boolean> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to add the last element,
// but that would make the code much less readable.
Boolean n = Boolean.valueOf (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (byte[] a) {
HashSet<Byte> hs = new HashSet<Byte> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to add the last element,
// but that would make the code much less readable.
Byte n = new Byte (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (char[] a) {
HashSet<Character> hs = new HashSet<Character> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to add the last element,
// but that would make the code much less readable.
Character n = new Character (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (float[] a) {
HashSet<Float> hs = new HashSet<Float> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to add the last element,
// but that would make the code much less readable.
Float n = new Float (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (short[] a) {
HashSet<Short> hs = new HashSet<Short> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to add the last element,
// but that would make the code much less readable.
Short n = new Short (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (int[] a) {
HashSet<Integer> hs = new HashSet<Integer> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to add the last element,
// but that would make the code much less readable.
Integer n = new Integer (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space. Equality checking
* uses the .equals() method for java.lang.Double.
*/
public static boolean noDuplicates (double[] a) {
HashSet<Double> hs = new HashSet<Double> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to create the last element,
// but that would make the code much less readable.
Double n = new Double (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (long[] a) {
HashSet<Long> hs = new HashSet<Long> ();
for (int i = 0; i < a.length; i++) {
// Could be optimized not to create the last element,
// but that would make the code much less readable.
Long n = new Long (a[i]);
if (hs.contains(n)) { return false; }
hs.add (n);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (String[] a) {
HashSet<String> hs = new HashSet<String> ();
for (int i = 0; i < a.length; i++) {
if (hs.contains(a[i])) { return false; }
// Could be optimized not to add the last element,
// but that would make the code much less readable.
hs.add (a[i]);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static boolean noDuplicates (Object[] a) {
HashSet<Object> hs = new HashSet<Object> ();
for (int i = 0; i < a.length; i++) {
if (hs.contains(a[i])) { return false; }
// Could be optimized not to add the last element,
// but that would make the code much less readable.
hs.add (a[i]);
}
return true;
}
/**
* @return true iff a does not contain duplicate elements
* using O(n) time and O(n) space.
*/
public static <T> boolean noDuplicates (List<T> a) {
HashSet<T> hs = new HashSet<T> ();
for (int i = 0; i < a.size(); i++) {
if (hs.contains(a.get(i))) { return false; }
// Could be optimized not to add the last element,
// but that would make the code much less readable.
hs.add (a.get(i));
}
return true;
}
///////////////////////////////////////////////////////////////////////////
/// Arrays as partial functions of int->int
///
/**
* @return true iff all elements of a are in [0..a.length) and a
* contains no duplicates.
**/
public static boolean fn_is_permutation(int[] a) {
// In the common case we expect to succeed so use as few loops as possible
boolean[] see = new boolean[a.length];
for (int i=0; i<a.length; i++) {
int n = a[i];
if (n < 0 || n >= a.length || see[n])
return false;
see[n] = true;
}
return true;
}
/**
* @return true iff no element of a maps to -1
**/
public static boolean fn_is_total(int[] a) {
return indexOf(a, -1) == -1; // not found
}
/**
* @return fresh array that is the identity function of the given length
**/
public static int[] fn_identity(int length) {
int[] result = new int[length];
for (int i=0; i < length; i++) {
result[i] = i;
}
return result;
}
/**
* Requires that fn_is_permutation(a) holds.
* @param a the input permutation
* @return fresh array which is the inverse of the given permutation.
* @see #fn_is_permutation(int[])
**/
public static int[] fn_inverse_permutation(int[] a) {
return fn_inverse(a, a.length);
}
/**
* @param a function from [0..a.length) to [0..arange)
* @return function from [0..arange) to [0..a.length) that is the inverse of a
* @exception UnsupportedOperationException when the function is not invertible
**/
public static int[] fn_inverse(int[] a, int arange) {
int[] result = new int[arange];
Arrays.fill(result, -1);
for (int i=0; i < a.length; i++) {
int ai = a[i];
if (ai != -1) {
if (result[ai] != -1) {
throw new UnsupportedOperationException("Not invertible");
}
result[ai] = i;
}
}
return result;
}
/**
* @param a function from [0..a.length) to [0..b.length)
* @param b function from [0..b.length) to range R
* @return function from [0..a.length) to range R that is the
* composition of a and b
**/
public static int[] fn_compose(int[] a, int[] b) {
int[] result = new int[a.length];
for (int i=0; i < a.length; i++) {
int inner = a[i];
if (inner == -1) {
result[i] = -1;
} else {
result[i] = b[inner];
}
}
return result;
}
///////////////////////////////////////////////////////////////////////////
/// Set operations, like subset, unions and intersections
///
// This implementation is O(n^2) when the smaller really is a subset, but
// might be quicker when it is not. Sorting both sets has (minimum
// and maximum) running time of Theta(n log n).
/**
* Whether smaller is a subset of bigger. The implementation is to
* use collections because we want to take advantage of HashSet's
* constant time membership tests.
**/
public static boolean isSubset(long[] smaller, long[] bigger) {
Set<Long> setBigger = new HashSet<Long>();
for (int i = 0; i < bigger.length; i++) {
setBigger.add(new Long(bigger[i]));
}
for (int i = 0; i < smaller.length; i++) {
Long elt = new Long(smaller[i]);
if (!setBigger.contains(elt)) return false;
}
return true;
}
// This implementation is O(n^2) when the smaller really is a subset, but
// might be quicker when it is not. Sorting both sets has (minimum
// and maximum) running time of Theta(n log n).
/**
* Whether smaller is a subset of bigger. The implementation is to
* use collections because we want to take advantage of HashSet's
* constant time membership tests.
**/
public static boolean isSubset(double[] smaller, double[] bigger) {
Set<Double> setBigger = new HashSet<Double>();
for (int i = 0; i < bigger.length; i++) {
setBigger.add(new Double(bigger[i]));
}
for (int i = 0; i < smaller.length; i++) {
Double elt = new Double(smaller[i]);
if (!setBigger.contains(elt)) return false;
}
return true;
}
// This implementation is O(n^2) when the smaller really is a subset, but
// might be quicker when it is not. Sorting both sets has (minimum
// and maximum) running time of Theta(n log n).
/**
* Whether smaller is a subset of bigger. The implementation is to
* use collections because we want to take advantage of HashSet's
* constant time membership tests.
**/
public static boolean isSubset(String[] smaller, String[] bigger) {
Set<String> setBigger = new HashSet<String>();
for (int i = 0; i < bigger.length; i++) {
setBigger.add(bigger[i]);
}
for (int i = 0; i < smaller.length; i++) {
if (!setBigger.contains(smaller[i])) return false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////
/// Array comparators
///
/**
* Compare two arrays lexically (element-by-element).
* If all shared elements are the same, but the lengths differ,
* then the shorter array is considered less.
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* numbers).
**/
public static final class IntArrayComparatorLexical implements Comparator<int[]> {
public int compare(int[] a1, int[] a2) {
if (a1 == a2)
return 0;
int len = Math.min(a1.length, a2.length);
for (int i=0; i<len; i++) {
if (a1[i] != a2[i])
return ((a1[i] > a2[i]) ? 1 : -1);
}
return a1.length - a2.length;
}
}
/**
* Compare two arrays lexically (element-by-element).
* If all shared elements are the same, but the lengths differ,
* then the shorter array is considered less.
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* numbers).
**/
public static final class LongArrayComparatorLexical implements Comparator<long[]> {
public int compare(long[] a1, long[] a2) {
if (a1 == a2)
return 0;
int len = Math.min(a1.length, a2.length);
for (int i=0; i<len; i++) {
if (a1[i] != a2[i])
return ((a1[i] > a2[i]) ? 1 : -1);
}
return a1.length - a2.length;
}
}
/**
* Compare two arrays lexically (element-by-element).
* If all shared elements are the same, but the lengths differ,
* then the shorter array is considered less.
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* numbers).
**/
public static final class DoubleArrayComparatorLexical implements Comparator<double[]> {
public int compare(double[] a1, double[] a2) {
if (a1 == a2)
return 0;
int len = Math.min(a1.length, a2.length);
for (int i=0; i<len; i++) {
int result = Double.compare(a1[i], a2[i]);
if (result != 0)
return (result);
}
return a1.length - a2.length;
}
}
/**
* Compare two arrays lexically (element-by-element).
* If all shared elements are the same, but the lengths differ,
* then the shorter array is considered less.
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* Strings).
**/
public static final class StringArrayComparatorLexical implements Comparator<String[]> {
public int compare(String[] a1, String[] a2) {
if (a1 == a2)
return 0;
int len = Math.min(a1.length, a2.length);
for (int i=0; i<len; i++) {
int tmp = 0;
if ((a1[i] == null) && (a2[i] == null))
tmp = 0;
else if (a1[i] == null)
tmp = -1;
else if (a2[i] == null)
tmp = 1;
else
tmp = a1[i].compareTo (a2[i]);
if (tmp != 0)
return (tmp);
}
return a1.length - a2.length;
}
}
/**
* Compare two arrays lexically (element-by-element).
* If all shared elements are the same, but the lengths differ,
* then the shorter array is considered less.
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* objects).
**/
public static final class ComparableArrayComparatorLexical<T extends Comparable<T>> implements Comparator<T[]> {
public int compare(T[] a1, T[] a2) {
if (a1 == a2)
return 0;
int len = Math.min(a1.length, a2.length);
for (int i=0; i<len; i++) {
T elt1 = a1[i];
T elt2 = a2[i];
// Make null compare smaller than anything else
if ((elt1 == null) && (elt2 == null))
continue;
if (elt1 == null)
return -1;
if (elt2 == null)
return 1;
int tmp = elt1.compareTo(elt2);
if (tmp != 0)
return tmp;
// Check the assumption that the two elements are equal.
assert elt1.equals(elt2);
}
return a1.length - a2.length;
}
}
/**
* Compare two arrays lexically (element-by-element).
* If all shared elements are the same, but the lengths differ,
* then the shorter array is considered less.
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* objects).
**/
public static final class ObjectArrayComparatorLexical implements Comparator<Object[]> {
public int compare(Object[] a1, Object[] a2) {
if (a1 == a2)
return 0;
int len = Math.min(a1.length, a2.length);
for (int i=0; i<len; i++) {
Object elt1 = a1[i];
Object elt2 = a2[i];
// Make null compare smaller than anything else
if ((elt1 == null) && (elt2 == null))
continue;
if (elt1 == null)
return -1;
if (elt2 == null)
return 1;
int tmp = elt1.hashCode() - elt2.hashCode();
if (tmp != 0)
return tmp;
// I'm counting on the fact that hashCode returns a different
// number for each Object in the system. This checks that assumption.
assert elt1.equals(elt2);
}
return a1.length - a2.length;
}
}
/**
* Compare two arrays first by length (a shorter array is considered
* less), and if of equal length compare lexically (element-by-element).
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* numbers).
**/
public static final class IntArrayComparatorLengthFirst implements Comparator<int[]> {
public int compare(int[] a1, int[] a2) {
if (a1 == a2)
return 0;
int tmp;
tmp = a1.length - a2.length;
if (tmp != 0)
return tmp;
for (int i=0; i<a1.length; i++) {
if (a1[i] != a2[i])
return ((a1[i] > a2[i]) ? 1 : -1);
}
return 0;
}
}
/**
* Compare two arrays first by length (a shorter array is considered
* less), and if of equal length compare lexically (element-by-element).
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* numbers).
**/
public static final class LongArrayComparatorLengthFirst implements Comparator<long[]> {
public int compare(long[] a1, long[] a2) {
if (a1 == a2)
return 0;
int lendiff = a1.length - a2.length;
if (lendiff != 0)
return lendiff;
long tmp;
for (int i=0; i<a1.length; i++) {
if (a1[i] != a2[i])
return ((a1[i] > a2[i]) ? 1 : -1);
}
return 0;
}
}
/**
* Compare two arrays first by length (a shorter array is considered
* less), and if of equal length compare lexically (element-by-element).
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* objects).
**/
public static final class ComparableArrayComparatorLengthFirst<T extends Comparable<T>> implements Comparator<T[]> {
public int compare(T[] a1, T[] a2) {
if (a1 == a2)
return 0;
int tmp;
tmp = a1.length - a2.length;
if (tmp != 0)
return tmp;
for (int i=0; i<a1.length; i++) {
T elt1 = a1[i];
T elt2 = a2[i];
// Make null compare smaller than anything else
if ((elt1 == null) && (elt2 == null))
continue;
if (elt1 == null)
return -1;
if (elt2 == null)
return 1;
tmp = elt1.compareTo(elt2);
if (tmp != 0)
return tmp;
// Check the assumption that the two elements are equal.
assert elt1.equals(elt2);
}
return 0;
}
}
/**
* Compare two arrays first by length (a shorter array is considered
* less), and if of equal length compare lexically (element-by-element).
* <p>
* Note: this comparator imposes orderings that are inconsistent with
* <tt>equals()</tt>. That is, it may return 0 if the arrays are not
* equal according to <tt>equals()</tt> (but do contain identical
* objects).
**/
public static final class ObjectArrayComparatorLengthFirst implements Comparator<Object[]> {
public int compare(Object[] a1, Object[] a2) {
if (a1 == a2)
return 0;
int tmp;
tmp = a1.length - a2.length;
if (tmp != 0)
return tmp;
for (int i=0; i<a1.length; i++) {
Object elt1 = a1[i];
Object elt2 = a2[i];
// Make null compare smaller than anything else
if ((elt1 == null) && (elt2 == null))
continue;
if (elt1 == null)
return -1;
if (elt2 == null)
return 1;
tmp = elt1.hashCode() - elt2.hashCode();
if (tmp != 0)
return tmp;
// I'm counting on the fact that hashCode returns a different
// number for each Object in the system. This checks that assumption.
assert elt1.equals(elt2);
}
return 0;
}
}
///////////////////////////////////////////////////////////////////////////
/// nullness
///
/**
* @return true iff some element of a is null (false if a is zero-sized)
**/
public static boolean any_null(Object[] a) {
if (a.length == 0)
return false;
// The cast ensures that the right version of IndexOfEq gets called.
return indexOfEq(a, (/*@Nullable*/ Object) null) >= 0;
}
/**
* @return true iff all elements of a are null (unspecified result if a is zero-sized)
**/
public static boolean all_null(Object[] a) {
for (int i=0; i<a.length; i++) {
if (! (a[i] == null))
return false;
}
return true;
}
/**
* @return true iff some element of a is null (false if a is zero-sized)
**/
public static boolean any_null(List<?> a) {
if (a.size() == 0)
return false;
// The cast ensures that the right version of IndexOfEq gets called.
return indexOfEq(a, (/*@Nullable*/ Object) null) >= 0;
}
/**
* @return true iff all elements of a are null (unspecified result if a is zero-sized)
**/
public static boolean all_null(List<?> a) {
for (int i=0; i<a.size(); i++) {
if (! (a.get(i) == null))
return false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////
/// javadoc hacks
///
// this is so that javadoc can find "java.util.Vector".
// "private static Vector v;" doesn't work, nor does
// "static { new java.util.Vector(); }", nor does "private Vector v".
// Yuck!
public Vector<?> javadocLossage;
}