diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-10-16 06:11:39 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-10-16 06:11:39 -0300 |
| commit | d2be5b73d7a5653ad5c8273c17284346baa6f1c7 (patch) | |
| tree | 9d3c6adb193f53588bd5d004fdf80c0381685351 /base/src/main/java/bjc/utils/funcutils | |
| parent | 0308029629a12711b849ea7765639b9b1f9e03d2 (diff) | |
| parent | d1d01769e7c55f7f62dc01cadf420d5f63424584 (diff) | |
Merge branch 'master' of github.com:bculkin2442/bjc-utils2
Diffstat (limited to 'base/src/main/java/bjc/utils/funcutils')
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()); + } +} |
