Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
processing.data.IntList Maven / Gradle / Ivy
package processing.data;
import java.io.File;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Random;
import processing.core.PApplet;
/**
* Helper class for a list of int values. Lists are designed
* to have some features of ArrayList , but to maintain the
* simplicity and efficiency of working with arrays.
* Functions such as sort() and shuffle() always act on
* the list itself. To get a sorted copy, use list.copy().sort() .
*
* @webref data:composite
* @webBrief Helper class for a list of ints
* @see FloatList
* @see StringList
*/
public class IntList implements Iterable {
protected int count;
protected int[] data;
public IntList() {
data = new int[10];
}
/**
* @nowebref
*/
public IntList(int length) {
data = new int[length];
}
/**
* @nowebref
*/
public IntList(int[] source) {
count = source.length;
data = new int[count];
System.arraycopy(source, 0, data, 0, count);
}
/**
* Construct an IntList from an iterable pile of objects.
* For instance, a float array, an array of strings, who knows.
* Un-parsable or null values will be set to 0.
* @nowebref
*/
public IntList(Iterable iterable) {
this(10);
for (Object o : iterable) {
if (o == null) {
append(0); // missing value default
} else if (o instanceof Number) {
append(((Number) o).intValue());
} else {
append(PApplet.parseInt(o.toString().trim()));
}
}
crop();
}
/**
* Construct an IntList from a random pile of objects.
* Un-parsable or null values will be set to zero.
*/
public IntList(Object... items) {
final int missingValue = 0; // nuts, can't be last/final/second arg
count = items.length;
data = new int[count];
int index = 0;
for (Object o : items) {
int value = missingValue;
if (o != null) {
if (o instanceof Number) {
value = ((Number) o).intValue();
} else {
value = PApplet.parseInt(o.toString().trim(), missingValue);
}
}
data[index++] = value;
}
}
static public IntList fromRange(int stop) {
return fromRange(0, stop);
}
static public IntList fromRange(int start, int stop) {
int count = stop - start;
IntList newbie = new IntList(count);
for (int i = 0; i < count; i++) {
newbie.set(i, start+i);
}
return newbie;
}
/**
* Improve efficiency by removing allocated but unused entries from the
* internal array used to store the data. Set to private, though it could
* be useful to have this public if lists are frequently making drastic
* size changes (from very large to very small).
*/
private void crop() {
if (count != data.length) {
data = PApplet.subset(data, 0, count);
}
}
/**
* Get the length of the list.
*
* @webref intlist:method
* @webBrief Get the length of the list
*/
public int size() {
return count;
}
public void resize(int length) {
if (length > data.length) {
int[] temp = new int[length];
System.arraycopy(data, 0, temp, 0, count);
data = temp;
} else if (length > count) {
Arrays.fill(data, count, length, 0);
}
count = length;
}
/**
* Remove all entries from the list.
*
* @webref intlist:method
* @webBrief Remove all entries from the list
*/
public void clear() {
count = 0;
}
/**
* Get an entry at a particular index.
*
* @webref intlist:method
* @webBrief Get an entry at a particular index
*/
public int get(int index) {
if (index >= this.count) {
throw new ArrayIndexOutOfBoundsException(index);
}
return data[index];
}
/**
* Set the entry at a particular index.
*
* @webref intlist:method
* @webBrief Set the entry at a particular index
*/
public void set(int index, int what) {
if (index >= count) {
data = PApplet.expand(data, index+1);
for (int i = count; i < index; i++) {
data[i] = 0;
}
count = index+1;
}
data[index] = what;
}
/** Just an alias for append(), but matches pop() */
public void push(int value) {
append(value);
}
public int pop() {
if (count == 0) {
throw new RuntimeException("Can't call pop() on an empty list");
}
int value = get(count-1);
count--;
return value;
}
/**
* Remove an element from the specified index
*
* @webref intlist:method
* @webBrief Remove an element from the specified index
*/
public int remove(int index) {
if (index < 0 || index >= count) {
throw new ArrayIndexOutOfBoundsException(index);
}
int entry = data[index];
// int[] outgoing = new int[count - 1];
// System.arraycopy(data, 0, outgoing, 0, index);
// count--;
// System.arraycopy(data, index + 1, outgoing, 0, count - index);
// data = outgoing;
// For most cases, this actually appears to be faster
// than arraycopy() on an array copying into itself.
for (int i = index; i < count-1; i++) {
data[i] = data[i+1];
}
count--;
return entry;
}
// Remove the first instance of a particular value,
// and return the index at which it was found.
@SuppressWarnings("unused")
public int removeValue(int value) {
int index = index(value);
if (index != -1) {
remove(index);
return index;
}
return -1;
}
// Remove all instances of a particular value,
// and return the number of values found and removed
@SuppressWarnings("unused")
public int removeValues(int value) {
int ii = 0;
for (int i = 0; i < count; i++) {
if (data[i] != value) {
data[ii++] = data[i];
}
}
int removed = count - ii;
count = ii;
return removed;
}
/**
* Add a new entry to the list.
*
* @webref intlist:method
* @webBrief Add a new entry to the list
*/
public void append(int value) {
if (count == data.length) {
data = PApplet.expand(data);
}
data[count++] = value;
}
public void append(int[] values) {
for (int v : values) {
append(v);
}
}
public void append(IntList list) {
for (int v : list.values()) { // will concat the list...
append(v);
}
}
/** Add this value, but only if it's not already in the list. */
@SuppressWarnings("unused")
public void appendUnique(int value) {
if (!hasValue(value)) {
append(value);
}
}
public void insert(int index, int value) {
insert(index, new int[] { value });
}
// same as splice
public void insert(int index, int[] values) {
if (index < 0) {
throw new IllegalArgumentException("insert() index cannot be negative: it was " + index);
}
if (index >= data.length) {
throw new IllegalArgumentException("insert() index " + index + " is past the end of this list");
}
int[] temp = new int[count + values.length];
// Copy the old values, but not more than already exist
System.arraycopy(data, 0, temp, 0, Math.min(count, index));
// Copy the new values into the proper place
System.arraycopy(values, 0, temp, index, values.length);
// if (index < count) {
// The index was inside count, so it's a true splice/insert
System.arraycopy(data, index, temp, index+values.length, count - index);
count = count + values.length;
// } else {
// // The index was past 'count', so the new count is weirder
// count = index + values.length;
// }
data = temp;
}
public void insert(int index, IntList list) {
insert(index, list.values());
}
// below are aborted attempts at more optimized versions of the code
// that are harder to read and debug...
// if (index + values.length >= count) {
// // We're past the current 'count', check to see if we're still allocated
// // index 9, data.length = 10, values.length = 1
// if (index + values.length < data.length) {
// // There's still room for these entries, even though it's past 'count'.
// // First clear out the entries leading up to it, however.
// for (int i = count; i < index; i++) {
// data[i] = 0;
// }
// data[index] =
// }
// if (index >= data.length) {
// int length = index + values.length;
// int[] temp = new int[length];
// System.arraycopy(data, 0, temp, 0, count);
// System.arraycopy(values, 0, temp, index, values.length);
// data = temp;
// count = data.length;
// } else {
//
// }
//
// } else if (count == data.length) {
// int[] temp = new int[count << 1];
// System.arraycopy(data, 0, temp, 0, index);
// temp[index] = value;
// System.arraycopy(data, index, temp, index+1, count - index);
// data = temp;
//
// } else {
// // data[] has room to grow
// // for() loop believed to be faster than System.arraycopy over itself
// for (int i = count; i > index; --i) {
// data[i] = data[i-1];
// }
// data[index] = value;
// count++;
// }
/** Return the first index of a particular value. */
public int index(int what) {
for (int i = 0; i < count; i++) {
if (data[i] == what) {
return i;
}
}
return -1;
}
/**
* Check if a number is a part of the data structure.
*
* @webref intlist:method
* @webBrief Check if a number is a part of the list
*/
public boolean hasValue(int value) {
for (int i = 0; i < count; i++) {
if (data[i] == value) {
return true;
}
}
return false;
}
/**
* Add one to a value.
*
* @webref intlist:method
* @webBrief Add one to a value
*/
public void increment(int index) {
if (count <= index) {
resize(index + 1);
}
data[index]++;
}
private void boundsProblem(int index, String method) {
final String msg = String.format("The list size is %d. " +
"You cannot %s() to element %d.", count, method, index);
throw new ArrayIndexOutOfBoundsException(msg);
}
/**
* Add to a value.
*
* @webref intlist:method
* @webBrief Add to a value
*/
public void add(int index, int amount) {
if (index < count) {
data[index] += amount;
} else {
boundsProblem(index, "add");
}
}
/**
* Subtract from a value.
*
* @webref intlist:method
* @webBrief Subtract from a value
*/
public void sub(int index, int amount) {
if (index < count) {
data[index] -= amount;
} else {
boundsProblem(index, "sub");
}
}
/**
* Multiply a value.
*
* @webref intlist:method
* @webBrief Multiply a value
*/
public void mult(int index, int amount) {
if (index < count) {
data[index] *= amount;
} else {
boundsProblem(index, "mult");
}
}
/**
* Divide a value.
*
* @webref intlist:method
* @webBrief Divide a value
*/
public void div(int index, int amount) {
if (index < count) {
data[index] /= amount;
} else {
boundsProblem(index, "div");
}
}
private void checkMinMax(String functionName) {
if (count == 0) {
String msg =
String.format("Cannot use %s() on an empty %s.",
functionName, getClass().getSimpleName());
throw new RuntimeException(msg);
}
}
/**
* Return the smallest value.
*
* @webref intlist:method
* @webBrief Return the smallest value
*/
public int min() {
checkMinMax("min");
int outgoing = data[0];
for (int i = 1; i < count; i++) {
if (data[i] < outgoing) outgoing = data[i];
}
return outgoing;
}
// returns the index of the minimum value.
// if there are ties, it returns the first one found.
@SuppressWarnings("unused")
public int minIndex() {
checkMinMax("minIndex");
int value = data[0];
int index = 0;
for (int i = 1; i < count; i++) {
if (data[i] < value) {
value = data[i];
index = i;
}
}
return index;
}
/**
* Return the largest value.
*
* @webref intlist:method
* @webBrief Return the largest value
*/
public int max() {
checkMinMax("max");
int outgoing = data[0];
for (int i = 1; i < count; i++) {
if (data[i] > outgoing) outgoing = data[i];
}
return outgoing;
}
// returns the index of the maximum value.
// if there are ties, it returns the first one found.
public int maxIndex() {
checkMinMax("maxIndex");
int value = data[0];
int index = 0;
for (int i = 1; i < count; i++) {
if (data[i] > value) {
value = data[i];
index = i;
}
}
return index;
}
public int sum() {
long amount = sumLong();
if (amount > Integer.MAX_VALUE) {
throw new RuntimeException("sum() exceeds " + Integer.MAX_VALUE + ", use sumLong()");
}
if (amount < Integer.MIN_VALUE) {
throw new RuntimeException("sum() less than " + Integer.MIN_VALUE + ", use sumLong()");
}
return (int) amount;
}
public long sumLong() {
long sum = 0;
for (int i = 0; i < count; i++) {
sum += data[i];
}
return sum;
}
/**
* Sorts the array, lowest to highest.
*
* @webref intlist:method
* @webBrief Sorts the array, lowest to highest
*/
public void sort() {
Arrays.sort(data, 0, count);
}
/**
* A sort in reverse. It's equivalent to running sort() and then
* reverse() , but is more efficient than running each separately.
*
* @webref intlist:method
* @webBrief Reverse sort, orders values from highest to lowest
*/
public void sortReverse() {
new Sort() {
@Override
public int size() {
return count;
}
@Override
public int compare(int a, int b) {
return data[b] - data[a];
}
@Override
public void swap(int a, int b) {
int temp = data[a];
data[a] = data[b];
data[b] = temp;
}
}.run();
}
/**
* Reverse the order of the list.
*
* @webref intlist:method
* @webBrief Reverse the order of the list elements
*/
public void reverse() {
int ii = count - 1;
for (int i = 0; i < count/2; i++) {
int t = data[i];
data[i] = data[ii];
data[ii] = t;
--ii;
}
}
/**
* Randomize the order of the list elements.
*
* @webref intlist:method
* @webBrief Randomize the order of the list elements
*/
@SuppressWarnings("unused")
public void shuffle() {
Random r = new Random();
int num = count;
while (num > 1) {
int value = r.nextInt(num);
num--;
int temp = data[num];
data[num] = data[value];
data[value] = temp;
}
}
/**
* Randomize the list order using the random() function from the specified
* sketch, allowing shuffle() to use its current randomSeed() setting.
*/
@SuppressWarnings("unused")
public void shuffle(PApplet sketch) {
int num = count;
while (num > 1) {
int value = (int) sketch.random(num);
num--;
int temp = data[num];
data[num] = data[value];
data[value] = temp;
}
}
/**
* Return a random value from the list.
*/
public int choice() {
if (count == 0) {
throw new ArrayIndexOutOfBoundsException("No entries in this IntList");
}
return data[(int) (Math.random() * count)];
}
// see notes in StringList
// /**
// * Return a random value from the list, using the
// * randomSeed() from the specified sketch object.
// */
// public int choice(PApplet sketch) {
// if (count == 0) {
// throw new ArrayIndexOutOfBoundsException("No entries in this IntList");
// }
// return data[(int) sketch.random(count)];
// }
public int removeChoice() {
if (count == 0) {
throw new ArrayIndexOutOfBoundsException("No entries in this IntList");
}
int index = (int) (Math.random() * count);
return remove(index);
}
public IntList copy() {
IntList outgoing = new IntList(data);
outgoing.count = count;
return outgoing;
}
/**
* Returns the actual array being used to store the data. For advanced users,
* this is the fastest way to access a large list. Suitable for iterating
* with a for() loop, but modifying the list will have terrible consequences.
*/
public int[] values() {
crop();
return data;
}
@Override
public Iterator iterator() {
return new Iterator<>() {
int index = -1;
public void remove() {
IntList.this.remove(index);
index--;
}
public Integer next() {
return data[++index];
}
public boolean hasNext() {
return index+1 < count;
}
};
}
@Deprecated
public int[] array() {
return toArray();
}
/**
* Create a new array with a copy of all the values.
*
* @return an array sized by the length of the list with each of the values.
* @webref intlist:method
* @webBrief Create a new array with a copy of all the values
*/
public int[] toArray() {
return toArray(null);
}
@Deprecated
public int[] array(int[] array) {
return toArray(array);
}
/**
* Copy values into the specified array. If the specified array is
* null or not the same size, a new array will be allocated.
*/
public int[] toArray(int[] array) {
if (array == null || array.length != count) {
array = new int[count];
}
System.arraycopy(data, 0, array, 0, count);
return array;
}
/**
* Returns a normalized version of this array. Called getPercent()
* for consistency with the Dict classes. It's a getter method because
* it needs to return a new list (because IntList/Dict can't do
* percentages or normalization in place on int values).
*/
@SuppressWarnings("unused")
public FloatList getPercent() {
double sum = 0;
for (float value : array()) {
sum += value;
}
FloatList outgoing = new FloatList(count);
for (int i = 0; i < count; i++) {
double percent = data[i] / sum;
outgoing.set(i, (float) percent);
}
return outgoing;
}
@SuppressWarnings("unused")
public IntList getSubset(int start) {
return getSubset(start, count - start);
}
@SuppressWarnings("unused")
public IntList getSubset(int start, int num) {
int[] subset = new int[num];
System.arraycopy(data, start, subset, 0, num);
return new IntList(subset);
}
public String join(String separator) {
if (count == 0) {
return "";
}
StringBuilder sb = new StringBuilder();
sb.append(data[0]);
for (int i = 1; i < count; i++) {
sb.append(separator);
sb.append(data[i]);
}
return sb.toString();
}
public void print() {
for (int i = 0; i < count; i++) {
System.out.format("[%d] %d%n", i, data[i]);
}
}
/**
* Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
*/
public void save(File file) {
PrintWriter writer = PApplet.createWriter(file);
write(writer);
writer.close();
}
/**
* Write entries to a PrintWriter, one per line
*/
public void write(PrintWriter writer) {
for (int i = 0; i < count; i++) {
writer.println(data[i]);
}
writer.flush();
}
/**
* Return this dictionary as a String in JSON format.
*/
public String toJSON() {
return "[ " + join(", ") + " ]";
}
@Override
public String toString() {
return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
}
}