summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/funcutils
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-10-16 06:11:39 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-10-16 06:11:39 -0300
commitd2be5b73d7a5653ad5c8273c17284346baa6f1c7 (patch)
tree9d3c6adb193f53588bd5d004fdf80c0381685351 /base/src/main/java/bjc/utils/funcutils
parent0308029629a12711b849ea7765639b9b1f9e03d2 (diff)
parentd1d01769e7c55f7f62dc01cadf420d5f63424584 (diff)
Merge branch 'master' of github.com:bculkin2442/bjc-utils2
Diffstat (limited to 'base/src/main/java/bjc/utils/funcutils')
-rw-r--r--base/src/main/java/bjc/utils/funcutils/FileUtils.java20
-rw-r--r--base/src/main/java/bjc/utils/funcutils/FuncUtils.java43
-rw-r--r--base/src/main/java/bjc/utils/funcutils/ListUtils.java132
-rw-r--r--base/src/main/java/bjc/utils/funcutils/SetUtils.java24
-rw-r--r--base/src/main/java/bjc/utils/funcutils/StringUtils.java216
-rw-r--r--base/src/main/java/bjc/utils/funcutils/TestUtils.java44
6 files changed, 177 insertions, 302 deletions
diff --git a/base/src/main/java/bjc/utils/funcutils/FileUtils.java b/base/src/main/java/bjc/utils/funcutils/FileUtils.java
index 0fd3db0..04ac6b0 100644
--- a/base/src/main/java/bjc/utils/funcutils/FileUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/FileUtils.java
@@ -13,26 +13,28 @@ import java.util.function.BiPredicate;
*/
public class FileUtils {
/*
- * @NOTE If it becomes necessary, write another overload for this with
- * all the buttons and knobs from walkFileTree.
+ * @NOTE
+ *
+ * If it becomes necessary, write another overload for this with all the
+ * buttons and knobs from walkFileTree.
*/
/**
* Traverse a directory recursively. This is a depth-first traversal.
*
* @param root
- * The directory to start the traversal at.
+ * The directory to start the traversal at.
*
* @param predicate
- * The predicate to determine whether or not to traverse a
- * directory.
+ * The predicate to determine whether or not to traverse
+ * a directory.
*
* @param action
- * The action to invoke upon each file in the directory.
- * Returning true means to continue the traversal, returning
- * false stops it.
+ * The action to invoke upon each file in the directory.
+ * Returning true means to continue the traversal,
+ * returning false stops it.
*
* @throws IOException
- * If the walk throws an exception.
+ * If the walk throws an exception.
*
*/
public static void traverseDirectory(final Path root, final BiPredicate<Path, BasicFileAttributes> predicate,
diff --git a/base/src/main/java/bjc/utils/funcutils/FuncUtils.java b/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
index 2e55a3d..ff9fefb 100644
--- a/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
@@ -1,6 +1,7 @@
package bjc.utils.funcutils;
import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.UnaryOperator;
@@ -16,16 +17,16 @@ public class FuncUtils {
* function.
*
* @param <A>
- * The initial type of the function.
+ * The initial type of the function.
*
* @param <B>
- * The intermediate type of the function.
+ * The intermediate type of the function.
*
* @param <C>
- * The terminal type of the function.
+ * The terminal type of the function.
*
* @param func
- * The function to transform.
+ * The function to transform.
*
* @return The function transformed into a unary function returning a
* function.
@@ -40,13 +41,13 @@ public class FuncUtils {
* Do the specified action the specified number of times.
*
* @param nTimes
- * The number of times to do the action.
+ * The number of times to do the action.
*
* @param cons
- * The action to perform.
+ * The action to perform.
*/
public static void doTimes(final int nTimes, final Consumer<Integer> cons) {
- for(int i = 0; i < nTimes; i++) {
+ for (int i = 0; i < nTimes; i++) {
cons.accept(i);
}
}
@@ -55,15 +56,35 @@ public class FuncUtils {
* Return an operator that executes until it converges.
*
* @param op
- * The operator to execute.
+ * The operator to execute.
*
* @param maxTries
- * The maximum amount of times to apply the function in an
- * attempt to cause it to converge.
+ * The maximum amount of times to apply the function in
+ * an attempt to cause it to converge.
*
* @return The requested operator.
*/
public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op, final int maxTries) {
+ return converge(op, (nw, old) -> nw.equals(old), maxTries);
+ }
+
+ /**
+ * Return an operator that executes until it converges.
+ *
+ * @param op
+ * The operator to execute.
+ * @param converged
+ * The predicate to execute to check if the function has
+ * converged.
+ *
+ * @param maxTries
+ * The maximum amount of times to apply the function in
+ * an attempt to cause it to converge.
+ *
+ * @return The requested operator.
+ */
+ public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op, final BiPredicate<T, T> converged,
+ final int maxTries) {
return (val) -> {
T newVal = op.apply(val);
T oldVal;
@@ -75,7 +96,7 @@ public class FuncUtils {
newVal = op.apply(newVal);
tries += 1;
- } while(!newVal.equals(oldVal) && tries < maxTries);
+ } while (!converged.test(newVal, oldVal) && tries < maxTries);
return newVal;
};
diff --git a/base/src/main/java/bjc/utils/funcutils/ListUtils.java b/base/src/main/java/bjc/utils/funcutils/ListUtils.java
index 55e0afa..b99c8a0 100644
--- a/base/src/main/java/bjc/utils/funcutils/ListUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/ListUtils.java
@@ -25,12 +25,12 @@ public class ListUtils {
* spaces.
*
* @param input
- * The list of tokens to collapse.
+ * The list of tokens to collapse.
*
* @return The collapsed string of tokens.
*/
public static String collapseTokens(final IList<String> input) {
- if(input == null) throw new NullPointerException("Input must not be null");
+ if (input == null) throw new NullPointerException("Input must not be null");
return collapseTokens(input, "");
}
@@ -40,32 +40,32 @@ public class ListUtils {
* separator after each token.
*
* @param input
- * The list of tokens to collapse.
+ * The list of tokens to collapse.
*
* @param seperator
- * The separator to use for separating tokens.
+ * The separator to use for separating tokens.
*
* @return The collapsed string of tokens.
*/
public static String collapseTokens(final IList<String> input, final String seperator) {
- if(input == null) {
+ if (input == null) {
throw new NullPointerException("Input must not be null");
- } else if(seperator == null) {
+ } else if (seperator == null) {
throw new NullPointerException("Seperator must not be null");
}
- if(input.getSize() < 1) {
+ if (input.getSize() < 1) {
return "";
- } else if(input.getSize() == 1) {
+ } else if (input.getSize() == 1) {
return input.first();
} else {
final StringBuilder state = new StringBuilder();
int i = 1;
- for(final String itm : input.toIterable()) {
+ for (final String itm : input.toIterable()) {
state.append(itm);
- if(i != input.getSize()) {
+ if (i != input.getSize()) {
state.append(seperator);
}
@@ -80,17 +80,17 @@ public class ListUtils {
* Select a number of random items from the list without replacement.
*
* @param <E>
- * The type of items to select.
+ * The type of items to select.
*
* @param list
- * The list to select from.
+ * The list to select from.
*
* @param number
- * The number of items to selet.
+ * The number of items to selet.
*
* @param rng
- * A function that creates a random number from 0 to the desired
- * number.
+ * A function that creates a random number from 0 to the
+ * desired number.
*
* @return A new list containing the desired number of items randomly
* selected from the specified list without replacement.
@@ -104,7 +104,7 @@ public class ListUtils {
final Iterator<E> itr = list.toIterable().iterator();
E element = null;
- for(final int index = 0; itr.hasNext(); element = itr.next()) {
+ for (final int index = 0; itr.hasNext(); element = itr.next()) {
/* n - m */
final int winningChance = number - selected.getSize();
@@ -112,7 +112,7 @@ public class ListUtils {
final int totalChance = total - (index - 1);
/* Probability of selecting the t+1'th element */
- if(NumberUtils.isProbable(winningChance, totalChance, rng)) {
+ if (NumberUtils.isProbable(winningChance, totalChance, rng)) {
selected.add(element);
}
}
@@ -124,17 +124,17 @@ public class ListUtils {
* Select a number of random items from the list, with replacement.
*
* @param <E>
- * The type of items to select.
+ * The type of items to select.
*
* @param list
- * The list to select from.
+ * The list to select from.
*
* @param number
- * The number of items to select.
+ * The number of items to select.
*
* @param rng
- * A function that creates a random number from 0 to the desired
- * number.
+ * A function that creates a random number from 0 to the
+ * desired number.
*
* @return A new list containing the desired number of items randomly
* selected from the specified list.
@@ -143,7 +143,7 @@ public class ListUtils {
final Function<Integer, Integer> rng) {
final IList<E> selected = new FunctionalList<>(new ArrayList<>(number));
- for(int i = 0; i < number; i++) {
+ for (int i = 0; i < number; i++) {
selected.add(list.randItem(rng));
}
@@ -155,26 +155,27 @@ public class ListUtils {
* for more than one element in a partition.
*
* @param <E>
- * The type of elements in the list to partition.
+ * The type of elements in the list to partition.
*
* @param input
- * The list to partition.
+ * The list to partition.
*
* @param counter
- * The function to determine the count for each element for.
+ * The function to determine the count for each element
+ * for.
*
* @param partitionSize
- * The number of elements to put in each partition.
+ * The number of elements to put in each partition.
*
* @return A list partitioned according to the above rules.
*/
public static <E> IList<IList<E>> groupPartition(final IList<E> input, final Function<E, Integer> counter,
final int partitionSize) {
- if(input == null) {
+ if (input == null) {
throw new NullPointerException("Input list must not be null");
- } else if(counter == null) {
+ } else if (counter == null) {
throw new NullPointerException("Counter must not be null");
- } else if(partitionSize < 1 || partitionSize > input.getSize()) {
+ } else if (partitionSize < 1 || partitionSize > input.getSize()) {
final String fmt = "%d is not a valid partition size. Must be between 1 and %d";
final String msg = String.format(fmt, partitionSize, input.getSize());
@@ -190,11 +191,11 @@ public class ListUtils {
final GroupPartIteration<E> it = new GroupPartIteration<>(returned, rejected, partitionSize, counter);
/* Run up to a certain number of passes. */
- for(int numberOfIterations = 0; numberOfIterations < MAX_NTRIESPART
+ for (int numberOfIterations = 0; numberOfIterations < MAX_NTRIESPART
&& !rejected.isEmpty(); numberOfIterations++) {
input.forEach(it);
- if(rejected.isEmpty()) {
+ if (rejected.isEmpty()) {
/* Nothing was rejected, so we're done. */
return returned;
}
@@ -212,10 +213,10 @@ public class ListUtils {
* Merge the contents of a bunch of lists together into a single list.
*
* @param <E>
- * The type of value in this lists.
+ * The type of value in this lists.
*
* @param lists
- * The values in the lists to merge.
+ * The values in the lists to merge.
*
* @return A list containing all the elements of the lists.
*/
@@ -223,8 +224,8 @@ public class ListUtils {
public static <E> IList<E> mergeLists(final IList<E>... lists) {
final IList<E> returned = new FunctionalList<>();
- for(final IList<E> list : lists) {
- for(final E itm : list.toIterable()) {
+ for (final IList<E> list : lists) {
+ for (final E itm : list.toIterable()) {
returned.add(itm);
}
}
@@ -236,24 +237,24 @@ public class ListUtils {
* Pad the provided list out to the desired size.
*
* @param <E>
- * The type of elements in the list.
+ * The type of elements in the list.
*
* @param list
- * The list to pad out.
+ * The list to pad out.
*
* @param counter
- * The function to count elements with.
+ * The function to count elements with.
*
* @param size
- * The desired size of the list.
+ * The desired size of the list.
*
* @param padder
- * The function to get elements to pad with.
+ * The function to get elements to pad with.
*
* @return The list, padded to the desired size.
*
* @throws IllegalArgumentException
- * If the list couldn't be padded to the desired size.
+ * If the list couldn't be padded to the desired size.
*/
public static <E> IList<E> padList(final IList<E> list, final Function<E, Integer> counter, final int size,
final Supplier<E> padder) {
@@ -261,22 +262,22 @@ public class ListUtils {
final IList<E> returned = new FunctionalList<>();
- for(final E itm : list.toIterable()) {
+ for (final E itm : list.toIterable()) {
count += counter.apply(itm);
returned.add(itm);
}
- if(count % size != 0) {
+ if (count % size != 0) {
/* We need to pad */
int needed = count % size;
int threshold = 0;
- while(needed > 0 && threshold <= MAX_NTRIESPART) {
+ while (needed > 0 && threshold <= MAX_NTRIESPART) {
final E val = padder.get();
final int newCount = counter.apply(val);
- if(newCount <= needed) {
+ if (newCount <= needed) {
returned.add(val);
threshold = 0;
@@ -287,7 +288,7 @@ public class ListUtils {
}
}
- if(threshold > MAX_NTRIESPART) {
+ if (threshold > MAX_NTRIESPART) {
final String fmt = "Heuristic (more than %d iterations of attempting to pad) detected an unpaddable list. (%s)\nPartially padded list: %S";
final String msg = String.format(fmt, MAX_NTRIESPART, list.toString(),
@@ -300,11 +301,18 @@ public class ListUtils {
return returned;
}
+ /**
+ * Convert a list of longs into an array of longs.
+ *
+ * @param list
+ * The list to convert.
+ * @return The list as an array.
+ */
public static long[] toPrimitive(List<Long> list) {
long[] res = new long[list.size()];
int idx = 0;
- for(long val : list) {
+ for (long val : list) {
res[idx] = val;
idx += 1;
@@ -320,7 +328,7 @@ public class ListUtils {
* pg 322)
*
* @param list
- * The list to generate permutations from.
+ * The list to generate permutations from.
* @return The list of permutations of the list.
*/
public static <T> List<List<T>> permuteList(List<T> list) {
@@ -329,17 +337,17 @@ public class ListUtils {
/*
* Special-case small usages.
*/
- if(list.size() == 0) {
+ if (list.size() == 0) {
return permutes;
}
- if(list.size() == 1) {
+ if (list.size() == 1) {
permutes.add(list);
return permutes;
}
- if(list.size() == 2) {
+ if (list.size() == 2) {
T elm1 = list.get(0);
T elm2 = list.get(1);
@@ -363,13 +371,13 @@ public class ListUtils {
int[] auxC = new int[list.size()];
int[] auxO = new int[list.size()];
- for(int i = 0; i < list.size(); i++) {
+ for (int i = 0; i < list.size(); i++) {
auxC[i] = 0;
auxO[i] = 1;
}
List<T> currentPermute = new ArrayList<>(list.size());
- for(T elm : list) {
+ for (T elm : list) {
currentPermute.add(elm);
}
permutes.add(currentPermute);
@@ -377,18 +385,18 @@ public class ListUtils {
int j = list.size() - 1;
int s = 0;
- while(true) {
+ while (true) {
int q = auxC[j] + auxO[j];
- if(q < 0) {
+ if (q < 0) {
auxO[j] = -auxO[j];
j -= 1;
continue;
}
- if(q == j) {
- if(j == 0) break;
+ if (q == j) {
+ if (j == 0) break;
s += 1;
@@ -406,7 +414,7 @@ public class ListUtils {
auxC[j] = q;
currentPermute = new ArrayList<>(list.size());
- for(T elm : list) {
+ for (T elm : list) {
currentPermute.add(elm);
}
permutes.add(currentPermute);
@@ -418,12 +426,6 @@ public class ListUtils {
return permutes;
}
- private static <T> List<List<T>> powerList(List<T> list) {
- List<List<T>> results = new LinkedList<>();
-
- return results;
- }
-
private static <T> void swapList(List<T> list, int a, int b) {
T tmp = list.get(a);
diff --git a/base/src/main/java/bjc/utils/funcutils/SetUtils.java b/base/src/main/java/bjc/utils/funcutils/SetUtils.java
index eac417c..d57ac00 100644
--- a/base/src/main/java/bjc/utils/funcutils/SetUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/SetUtils.java
@@ -5,10 +5,21 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+/**
+ * Various utility functions dealing with sets.
+ * @author bjculkin
+ *
+ */
public class SetUtils {
+ /**
+ * Create a power-set (set of all subsets) of a given set.
+ * @param originalSet The set to create a power-set of.
+ * @return The power-set of the set.
+ */
public static <T> Set<Set<T>> powerSet(Set<T> originalSet) {
Set<Set<T>> sets = new HashSet<Set<T>>();
+ // Special-case empty input
if (originalSet.isEmpty()) {
sets.add(new HashSet<T>());
return sets;
@@ -16,13 +27,18 @@ public class SetUtils {
List<T> list = new ArrayList<T>(originalSet);
+ // Add original set to list.
T head = list.get(0);
+ // Trim leading element from set.
Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
- for (Set<T> set : powerSet(rest)) {
+ Set<Set<T>> remSets = powerSet(rest);
+
+ for (Set<T> set : remSets) {
Set<T> newSet = new HashSet<T>();
+ // Create a new set with the removed element.
newSet.add(head);
newSet.addAll(set);
@@ -33,6 +49,12 @@ public class SetUtils {
return sets;
}
+ /**
+ * Utility method for set construction.
+ * @param elms The elements to stick in the set.
+ * @return A set containing the specified elements.
+ */
+ @SafeVarargs
public static <T> Set<T> toSet(T... elms) {
Set<T> set = new HashSet<>();
diff --git a/base/src/main/java/bjc/utils/funcutils/StringUtils.java b/base/src/main/java/bjc/utils/funcutils/StringUtils.java
index 8e75f79..7a4ee20 100644
--- a/base/src/main/java/bjc/utils/funcutils/StringUtils.java
+++ b/base/src/main/java/bjc/utils/funcutils/StringUtils.java
@@ -254,220 +254,4 @@ public class StringUtils {
}
return strings;
}
-
- public static boolean levelContains(String haystack, String... needles) {
- int nestLevel = 0;
- int i = 0;
-
- boolean prevCharWasSlash = false;
- boolean inString = false;
-
- char stringEnder = ' ';
-
- while(i < haystack.length()) {
- if(inString == false && nestLevel == 0) {
- for(String needle : needles) {
- if(haystack.regionMatches(i, needle, 0, needle.length())) {
- return true;
- }
- }
- }
-
- if(inString) {
- if(prevCharWasSlash == true) {
- prevCharWasSlash = false;
- } else if (haystack.charAt(i) == stringEnder) {
- inString = false;
- }
- } else {
- switch(haystack.charAt(i)) {
- case '\'':
- inString = true;
- stringEnder = '\'';
- break;
- case '\"':
- inString = true;
- stringEnder = '\"';
- break;
- case '(':
- case '[':
- case '{':
- case '<':
- nestLevel += 1;
- break;
- case ')':
- case ']':
- case '}':
- case '>':
- nestLevel = Math.max(0, nestLevel - 1);
- break;
- }
- }
-
- i += 1;
- }
-
- return false;
- }
-
- public static List<String> levelSplit(String phrase, String... splits) {
- return levelSplit(phrase, false, splits);
- }
-
- public static List<String> levelSplit(String phrase, boolean keepDelims, String... splits) {
- String work = phrase;
-
- List<String> strangs = new ArrayList<>();
-
- int nestLevel = 0;
- int i = 0;
-
- boolean prevCharWasSlash = false;
- boolean inString = false;
-
- char stringEnder = ' ';
-
- // Shortcut empty strings
- if(phrase.equals("")) {
- strangs.add("");
-
- return strangs;
- }
-
- while(i < work.length()) {
- if(inString == false && nestLevel == 0) {
- for(String split : splits) {
- if(work.regionMatches(i, split, 0, split.length())) {
- strangs.add(work.substring(0, i));
-
- if(keepDelims) strangs.add(split);
-
- work = work.substring(i + split.length());
- i = 0;
-
- continue;
- }
- }
- }
-
- if(inString) {
- if(prevCharWasSlash == true) {
- prevCharWasSlash = false;
- } else if (work.charAt(i) == stringEnder) {
- inString = false;
- }
- } else {
- /*
- * @TODO Ben Culkin 9/4/18
- *
- * This currently crashes if the string ends
- * with one of the delimiters in question.
- */
- switch(work.charAt(i)) {
- case '\'':
- inString = true;
- stringEnder = '\'';
- break;
- case '\"':
- inString = true;
- stringEnder = '\"';
- break;
- case '(':
- case '[':
- case '{':
- case '<':
- nestLevel += 1;
- break;
- case ')':
- case ']':
- case '}':
- case '>':
- nestLevel = Math.max(0, nestLevel - 1);
- break;
- }
- }
-
- i += 1;
- }
-
- strangs.add(work);
-
- return strangs;
- }
-
- public static List<String> levelSplitRX(String phrase, String patt) {
- return levelSplit(phrase, false, patt);
- }
-
- // @TODO @FIXME
- //
- // This doesn't seem like its working
- public static List<String> levelSplitRX(String phrase, boolean keepDelims, String patt) {
- Pattern pat = Pattern.compile(patt);
-
- String work = phrase;
- Matcher mat = pat.matcher(work);
-
- List<String> strangs = new ArrayList<>();
-
- int nestLevel = 0;
- int i = 0;
-
- boolean prevCharWasSlash = false;
- boolean inString = false;
-
- char stringEnder = ' ';
-
- while(i < work.length()) {
- if(inString == false && nestLevel == 0) {
- if(mat.find(i)) {
- strangs.add(work.substring(0, i));
- if(keepDelims) strangs.add(mat.group());
- work = work.substring(mat.end());
- i = 0;
-
- mat = pat.matcher(work);
-
- continue;
- }
- }
-
- if(inString) {
- if(prevCharWasSlash == true) {
- prevCharWasSlash = false;
- } else if (work.charAt(i) == stringEnder) {
- inString = false;
- }
- } else {
- switch(work.charAt(i)) {
- case '\'':
- inString = true;
- stringEnder = '\'';
- break;
- case '\"':
- inString = true;
- stringEnder = '\"';
- break;
- case '(':
- case '[':
- case '{':
- case '<':
- nestLevel += 1;
- break;
- case ')':
- case ']':
- case '}':
- case '>':
- nestLevel = Math.max(0, nestLevel - 1);
- break;
- }
- }
-
- i += 1;
- }
-
- strangs.add(work);
-
- return strangs;
- }
}
diff --git a/base/src/main/java/bjc/utils/funcutils/TestUtils.java b/base/src/main/java/bjc/utils/funcutils/TestUtils.java
new file mode 100644
index 0000000..df44e7a
--- /dev/null
+++ b/base/src/main/java/bjc/utils/funcutils/TestUtils.java
@@ -0,0 +1,44 @@
+package bjc.utils.funcutils;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Utilities for testing.
+ *
+ * @author bjculkin
+ *
+ */
+public class TestUtils {
+ /**
+ * Assert an iterator provides a particular sequence of values.
+ *
+ * @param src
+ * The iterator to pull values from.
+ * @param vals
+ * The values to expect from the iterator.
+ */
+ public static <T> void assertIteratorEquals(Iterator<T> src, T... vals) {
+ for (T val : vals) {
+ assertEquals(val, src.next());
+ }
+ }
+
+ /**
+ * Assert an iterator provides a particular sequence of values.
+ *
+ * @param src
+ * The iterator to pull values from.
+ * @param hasMore
+ * The expected value of hasNext for the iterator.
+ * @param vals
+ * The values to expect from the iterator.
+ */
+ public static <T> void assertIteratorEquals(Iterator<T> src, boolean hasMore, T... vals) {
+ assertIteratorEquals(src, vals);
+
+ assertEquals(hasMore, src.hasNext());
+ }
+}