From bf9737ae3c61c638dca3a40ca847e784ddd750f3 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Sat, 13 Oct 2018 15:40:10 -0400 Subject: Pull out levelSplit/levelContains levelSplit/levelContains from the StringUtils class are now instead in the new LevelSplitter class in ioutils. This is so that new features of varying sorts can be added to those functions without cluttering up StringUtils. --- .../main/java/bjc/utils/funcutils/StringUtils.java | 217 +-------------------- 1 file changed, 1 insertion(+), 216 deletions(-) (limited to 'base/src/main/java/bjc/utils/funcutils') diff --git a/base/src/main/java/bjc/utils/funcutils/StringUtils.java b/base/src/main/java/bjc/utils/funcutils/StringUtils.java index 8e75f79..e8558c7 100644 --- a/base/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -7,6 +7,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import bjc.utils.data.BooleanToggle; +import bjc.utils.ioutils.LevelSplitter; import bjc.utils.parserutils.TokenUtils; import com.ibm.icu.text.BreakIterator; @@ -254,220 +255,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 levelSplit(String phrase, String... splits) { - return levelSplit(phrase, false, splits); - } - - public static List levelSplit(String phrase, boolean keepDelims, String... splits) { - String work = phrase; - - List 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 levelSplitRX(String phrase, String patt) { - return levelSplit(phrase, false, patt); - } - - // @TODO @FIXME - // - // This doesn't seem like its working - public static List levelSplitRX(String phrase, boolean keepDelims, String patt) { - Pattern pat = Pattern.compile(patt); - - String work = phrase; - Matcher mat = pat.matcher(work); - - List 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; - } } -- cgit v1.2.3 From 327c2a35bde7a13d77f343464e41e19e4a214790 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Sat, 13 Oct 2018 15:51:53 -0400 Subject: General cleanup and documentation. Cleanup files, and add missing comments in places. --- .../main/java/bjc/utils/funcutils/ListUtils.java | 132 +++++++++++---------- .../main/java/bjc/utils/funcutils/SetUtils.java | 24 +++- .../main/java/bjc/utils/funcutils/StringUtils.java | 1 - 3 files changed, 90 insertions(+), 67 deletions(-) (limited to 'base/src/main/java/bjc/utils/funcutils') 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 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 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 - * 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 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 - * 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 rng) { final IList 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 - * 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 IList> groupPartition(final IList input, final Function 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 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 - * 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 IList mergeLists(final IList... lists) { final IList returned = new FunctionalList<>(); - for(final IList list : lists) { - for(final E itm : list.toIterable()) { + for (final IList 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 - * 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 IList padList(final IList list, final Function counter, final int size, final Supplier padder) { @@ -261,22 +262,22 @@ public class ListUtils { final IList 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 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 List> permuteList(List 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 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 List> powerList(List list) { - List> results = new LinkedList<>(); - - return results; - } - private static void swapList(List 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 Set> powerSet(Set originalSet) { Set> sets = new HashSet>(); + // Special-case empty input if (originalSet.isEmpty()) { sets.add(new HashSet()); return sets; @@ -16,13 +27,18 @@ public class SetUtils { List list = new ArrayList(originalSet); + // Add original set to list. T head = list.get(0); + // Trim leading element from set. Set rest = new HashSet(list.subList(1, list.size())); - for (Set set : powerSet(rest)) { + Set> remSets = powerSet(rest); + + for (Set set : remSets) { Set newSet = new HashSet(); + // 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 Set toSet(T... elms) { Set 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 e8558c7..7a4ee20 100644 --- a/base/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -7,7 +7,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import bjc.utils.data.BooleanToggle; -import bjc.utils.ioutils.LevelSplitter; import bjc.utils.parserutils.TokenUtils; import com.ibm.icu.text.BreakIterator; -- cgit v1.2.3 From d1d01769e7c55f7f62dc01cadf420d5f63424584 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Sun, 14 Oct 2018 14:07:00 -0400 Subject: Testing --- .../main/java/bjc/utils/funcutils/FileUtils.java | 20 +++++----- .../main/java/bjc/utils/funcutils/FuncUtils.java | 43 +++++++++++++++------ .../main/java/bjc/utils/funcutils/TestUtils.java | 44 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 base/src/main/java/bjc/utils/funcutils/TestUtils.java (limited to 'base/src/main/java/bjc/utils/funcutils') 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 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 - * The initial type of the function. + * The initial type of the function. * * @param - * The intermediate type of the function. + * The intermediate type of the function. * * @param - * 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 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 UnaryOperator converge(final UnaryOperator 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 UnaryOperator converge(final UnaryOperator op, final BiPredicate 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/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 void assertIteratorEquals(Iterator 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 void assertIteratorEquals(Iterator src, boolean hasMore, T... vals) { + assertIteratorEquals(src, vals); + + assertEquals(hasMore, src.hasNext()); + } +} -- cgit v1.2.3