From ba07771f8333f1b098ab8a9ec9fec886b72b9cc0 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Wed, 13 Apr 2016 16:54:12 -0400 Subject: Removed old data types --- .../java/bjc/utils/cli/GenericCommandMode.java | 2 + .../src/main/java/bjc/utils/cli/ICommand.java | 4 +- .../components/ComponentDescriptionState.java | 1 + .../bjc/utils/components/IComponentRepository.java | 4 +- .../src/main/java/bjc/utils/data/GenHolder.java | 113 -------- .../src/main/java/bjc/utils/data/IHolder.java | 70 ----- BJC-Utils2/src/main/java/bjc/utils/data/IPair.java | 54 ---- BJC-Utils2/src/main/java/bjc/utils/data/Pair.java | 104 -------- .../java/bjc/utils/data/experimental/IHolder.java | 4 +- .../java/bjc/utils/data/experimental/IPair.java | 13 + .../src/main/java/bjc/utils/data/lazy/ILazy.java | 35 --- .../main/java/bjc/utils/data/lazy/LazyHolder.java | 284 --------------------- .../main/java/bjc/utils/data/lazy/LazyPair.java | 168 ------------ .../main/java/bjc/utils/data/lazy/NewLazyPair.java | 202 --------------- .../java/bjc/utils/funcdata/FunctionalList.java | 172 +++++++++---- .../java/bjc/utils/funcdata/FunctionalMap.java | 22 +- .../java/bjc/utils/funcdata/IFunctionalList.java | 47 +++- .../java/bjc/utils/funcdata/IFunctionalMap.java | 7 + .../main/java/bjc/utils/funcutils/EnumUtils.java | 4 +- .../main/java/bjc/utils/funcutils/ListUtils.java | 76 +++++- .../main/java/bjc/utils/funcutils/NumberUtils.java | 53 ++++ .../main/java/bjc/utils/gen/WeightedRandom.java | 21 +- 22 files changed, 358 insertions(+), 1102 deletions(-) delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/IPair.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/Pair.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java (limited to 'BJC-Utils2/src/main/java/bjc/utils') diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java index a1c4461..c52bb08 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java +++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java @@ -87,6 +87,8 @@ public class GenericCommandMode implements ICommandMode { + " while invoking it with the name of a topic will print the entry" + " for that topic")); + addCommandAlias("help", "man"); + // Add commands handled in a upper layer defaultHandlers.put("clear", new GenericCommand((args) -> { errorOutput.accept( diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java index 4cd2dd1..7029829 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java +++ b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java @@ -33,5 +33,7 @@ public interface ICommand { * * @return Whether or not this command is an alias of another */ - public boolean isAlias(); + public default boolean isAlias() { + return false; + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java index 6c374be..52a1999 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java +++ b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java @@ -8,6 +8,7 @@ package bjc.utils.components; */ public class ComponentDescriptionState { private String name; + private String description; private String author; diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java index c720015..348be3e 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java +++ b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java @@ -17,7 +17,9 @@ public interface IComponentRepository { * * @return A list of all the registered components */ - public IFunctionalList getComponentList(); + public default IFunctionalList getComponentList() { + return getComponents().valueList(); + } /** * Get all of the components this repository knows about diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java deleted file mode 100644 index bd87f07..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java +++ /dev/null @@ -1,113 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Holds a single value of a specific type. This is used for indirect - * references to data, and more specifically for accessing non-final - * variables from a lambda. AKA the identity monad - * - * This is an eager variant of {@link IHolder} - * - * @author ben - * - * @param - * The type of the data being held - */ -public class GenHolder implements IHolder { - /** - * The state this holder is responsible for. - */ - private T heldValue; - - /** - * Creates a new empty holder, with its state set to null - */ - public GenHolder() { - heldValue = null; - } - - /** - * Creates a new holder, with its state initialized to the provided - * value - * - * @param held - * The state to initialize this holder to. - */ - public GenHolder(T held) { - heldValue = held; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#doWith(java.util.function.Consumer) - */ - @Override - public void doWith(Consumer action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - action.accept(heldValue); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#map(java.util.function.Function) - */ - @Override - public IHolder map(Function transformer) { - if (transformer == null) { - throw new NullPointerException("Transformer must be non-null"); - } - - return new GenHolder<>(transformer.apply(heldValue)); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#transform(java.util.function.Function) - */ - @Override - public IHolder transform(Function transformer) { - if (transformer == null) { - throw new NullPointerException("Transformer must be non-null"); - } - - heldValue = transformer.apply(heldValue); - - return this; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IHolder#unwrap(java.util.function.Function) - */ - @Override - public E unwrap(Function unwrapper) { - if (unwrapper == null) { - throw new NullPointerException("Unwrapper must be null"); - } - - return unwrapper.apply(heldValue); - } - - @Override - public String toString() { - if (heldValue == null) { - return "(null)"; - } - - return heldValue.toString(); - } - - @Override - public IHolder bind(Function> binder) { - return binder.apply(heldValue); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java deleted file mode 100644 index a4f4013..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java +++ /dev/null @@ -1,70 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Generic interface for things that store a single value in a roughly - * monadic fashion - * - * @author ben - * - * @param - * The type of data being stored - */ -public interface IHolder { - - /** - * Call a provided function with the value being held - * - * @param action - * The function to call - */ - public void doWith(Consumer action); - - /** - * Return the result of applying the given transformation to the held - * value. Doesn't change the held value. - * - * @param - * The new type of the held value - * - * @param transformer - * The transformation to apply - * @return A holder with the transformed value - */ - public IHolder map(Function transformer); - - /** - * Apply the given transformation to the held value. Returns the holder - * for allowing chaining of transforms - * - * @param transformer - * The transform to apply to the value - * @return The holder - */ - public IHolder transform(Function transformer); - - /** - * Returns a raw mapped value, not contained in a GenHolder - * - * @param - * The type of the value that is the end result - * - * @param unwrapper - * The function to use for mapping the value - * @return The mapped value outside of a GenHolder - */ - public E unwrap(Function unwrapper); - - /** - * Bind the value in this holder to a new value - * - * @param - * The new type of the held value - * @param binder - * The function to do the binding with - * @return The bound value - */ - public IHolder bind(Function> binder); -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java deleted file mode 100644 index 98f425f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; - -/** - * An interface representing a pair of values - * - * @author ben - * - * @param - * The type stored in the left side of the pair - * @param - * The type stored in the right side of the pair - */ -public interface IPair { - /** - * Apply a function to the two internal values that returns a new pair. - * - * Is a monadic bind. - * - * @param - * The new left pair type - * @param - * The new right pair type - * @param binder - * The function to use as a bind - * @return The new pair - */ - public IPair bind( - BiFunction> binder); - - /** - * Execute an action with the values of this pair. Has no effect on the - * internal contents - * - * @param action - * The action to execute on the values - */ - public void doWith(BiConsumer action); - - /** - * Collapse this pair to a single value. Does not change the internal - * contents of this pair. - * - * @param - * The resulting type after merging - * - * @param merger - * The function to use to collapse the pair. - * @return The collapsed value. - */ - public E merge(BiFunction merger); -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java deleted file mode 100644 index 87727be..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java +++ /dev/null @@ -1,104 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; - -/** - * Holds a pair of values of two different types. - * - * Is an eager variant of {@link IPair} - * - * @author ben - * - * @param - * The type of the thing held on the left (first) - * @param - * The type of the thing held on the right (second) - */ -public class Pair implements IPair { - /** - * The left value of the pair - */ - protected L leftValue; - - /** - * The right value of the pair - */ - protected R rightValue; - - /** - * Create a new pair that holds two nulls. - */ - public Pair() { - - } - - /** - * Create a new pair holding the specified values. - * - * @param left - * The value to hold on the left. - * @param right - * The value to hold on the right. - */ - public Pair(L left, R right) { - leftValue = left; - rightValue = right; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer) - */ - @Override - public void doWith(BiConsumer action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - action.accept(leftValue, rightValue); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#merge(java.util.function.BiFunction) - */ - @Override - public E merge(BiFunction merger) { - if (merger == null) { - throw new NullPointerException("Merger must be non-null"); - } - - return merger.apply(leftValue, rightValue); - } - - @Override - public String toString() { - String leftValueString; - - if (leftValue != null) { - leftValueString = leftValue.toString(); - } else { - leftValueString = "(null)"; - } - - String rightValueString; - - if (rightValue != null) { - rightValueString = rightValue.toString(); - } else { - rightValueString = "(null)"; - } - - return "pair[l=" + leftValueString + ", r=" + rightValueString - + "]"; - } - - @Override - public IPair bind( - BiFunction> binder) { - return binder.apply(leftValue, rightValue); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java index 7d1d7a0..6ccf115 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java @@ -94,6 +94,8 @@ public interface IHolder { * @return The holder itself */ public default IHolder replace(ContainedType newValue) { - return transform((oldValue) -> newValue); + return transform((oldValue) -> { + return newValue; + }); } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java index fb9648e..f5ca240 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java @@ -1,5 +1,6 @@ package bjc.utils.data.experimental; +import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; @@ -81,4 +82,16 @@ public interface IPair { public default RightType getRight() { return merge((leftValue, rightValue) -> rightValue); } + + /** + * Immediately perfom the specified action with the contents of this pair + * @param consumer The action to perform on the pair + */ + public default void doWith(BiConsumer consumer) { + merge((leftValue, rightValue) -> { + consumer.accept(leftValue, rightValue); + + return null; + }); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java deleted file mode 100644 index a4fab67..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java +++ /dev/null @@ -1,35 +0,0 @@ -package bjc.utils.data.lazy; - -/** - * Interface for some maintenance operations on lazy objects - * - * @author ben - * - */ -public interface ILazy { - /** - * Check if this object has been materialized - * - * @return Whether or not this object has been materialized - */ - public boolean isMaterialized(); - - /** - * Check if there are pending actions that need to be applied - * - * @return Whether or not there are pending actions - */ - public boolean hasPendingActions(); - - /** - * Make this object materialize itelf - */ - public void materialize(); - - /** - * Make this object apply any pending objects - * - * As a requirement, will materialize the object if it is not materialized - */ - public void applyPendingActions(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java deleted file mode 100644 index 141d558..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java +++ /dev/null @@ -1,284 +0,0 @@ -package bjc.utils.data.lazy; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IFunctionalList; - -/** - * Holds a single value of a specific type. This is used for indirect - * references to data, and more specifically for accessing non-final - * variables from a lambda. AKA the identity monad - * - * This is a lazy variant of {@link IHolder} - * - * @author ben - * - * @param - * The type of the data being held - */ -public class LazyHolder implements IHolder, ILazy { - private static final class LazyHolderHolder - implements IHolder { - private Supplier> holderSource; - - private IHolder holder; - - private IFunctionalList> actions = new FunctionalList<>(); - - public LazyHolderHolder(Supplier> source) { - - holderSource = source; - } - - @Override - public void doWith(Consumer action) { - actions.add((val) -> { - action.accept(val); - - return val; - }); - } - - @Override - public IHolder map(Function transformer) { - // TODO implement me - throw new UnsupportedOperationException( - "Mapping is not yet supported on bound holders"); - } - - @Override - public IHolder transform(Function transformer) { - actions.add(transformer); - - return this; - } - - @Override - public E unwrap(Function unwrapper) { - if (holder == null) { - holder = holderSource.get(); - } - - if (!actions.isEmpty()) { - actions.forEach((transform) -> { - holder.transform(transform); - }); - } - - return holder.unwrap(unwrapper); - } - - @Override - public IHolder bind(Function> binder) { - return new LazyHolderHolder<>(() -> { - return binder.apply(unwrap((val) -> val)); - }); - } - - @Override - public String toString() { - if (holderSource == null) { - if (holder == null) { - return "(null)"; - } - - return holder.toString(); - } - - if (holder == null) { - return "(unmaterialized values)"; - } - - return holder.toString(); - } - } - - private static final class LazyHolderSupplier - implements Supplier { - private IFunctionalList> pendingActions; - private Function pendingTransform; - - private T2 heldValue; - private Supplier heldSource; - - public LazyHolderSupplier(IFunctionalList> actons, - Function transform, T2 heldValue, - Supplier heldSource) { - // Resolve latent bug I just realized. After a map, adding new - // actions to the original holder could've resulted in changes - // to all unactualized mapped values from that holder - pendingActions = new FunctionalList<>(); - - for (Function action : actons.toIterable()) { - pendingActions.add(action); - } - - this.pendingTransform = transform; - this.heldValue = heldValue; - this.heldSource = heldSource; - } - - @Override - public NewT get() { - if (heldValue == null) { - return pendingActions.reduceAux(heldSource.get(), - Function::apply, pendingTransform::apply); - } - - return pendingActions.reduceAux(heldValue, - Function::apply, pendingTransform::apply); - } - } - - /** - * List of queued actions to be performed on realized values - */ - private IFunctionalList> actions = new FunctionalList<>(); - - /** - * The value internally held by this lazy holder - */ - private T heldValue; - - /** - * The source for a value held by this lazy holder - */ - private Supplier heldSource; - - /** - * Create a new lazy holder with the given supplier - * - * @param source - * The supplier for a value when it is neededs - */ - public LazyHolder(Supplier source) { - if (source == null) { - throw new NullPointerException("Source must be non-null"); - } - - heldSource = source; - heldValue = null; - } - - /** - * Create a new lazy holder with the given value - * - * @param value - * The value held in the holder - */ - public LazyHolder(T value) { - heldSource = () -> value; - } - - @Override - public void doWith(Consumer action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - transform((value) -> { - // Do the action with the value - action.accept(value); - - // Return the untransformed value - return value; - }); - } - - @Override - public IHolder map(Function transform) { - if (transform == null) { - throw new NullPointerException("Transform must be non-null"); - } - - // Don't actually map until we need to - return new LazyHolder<>(new LazyHolderSupplier<>(actions, - transform, heldValue, heldSource)); - } - - @Override - public IHolder transform(Function transform) { - if (transform == null) { - throw new NullPointerException("Transform must be non-null"); - } - - // Queue the transform until we need to apply it - actions.add(transform); - - return this; - } - - @Override - public E unwrap(Function unwrapper) { - if (unwrapper == null) { - throw new NullPointerException("Unwrapper must be null"); - } - - // Actualize ourselves - if (heldValue == null) { - heldValue = heldSource.get(); - } - - // Apply all pending transforms - actions.forEach((action) -> heldValue = action.apply(heldValue)); - - return unwrapper.apply(heldValue); - } - - @Override - public boolean isMaterialized() { - if (heldSource != null) { - // We're materialized if a value exists - return heldValue == null; - } - - // We're materialized by default - return true; - } - - @Override - public boolean hasPendingActions() { - return actions.isEmpty(); - } - - @Override - public void materialize() { - // Only materialize if we haven't already - if (!isMaterialized()) { - heldValue = heldSource.get(); - } - } - - @Override - public void applyPendingActions() { - materialize(); - - actions.forEach((action) -> { - heldValue = action.apply(heldValue); - }); - } - - @Override - public IHolder bind(Function> binder) { - return new LazyHolderHolder<>(() -> { - return binder.apply(unwrap((val) -> val)); - }); - } - - @Override - public String toString() { - if (isMaterialized()) { - if (hasPendingActions()) { - return heldValue.toString() + " (has pending actions)"; - } - - return heldValue.toString(); - } - - return "(unmaterialized value)"; - } -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java deleted file mode 100644 index dcaeeba..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java +++ /dev/null @@ -1,168 +0,0 @@ -package bjc.utils.data.lazy; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; - -/** - * A lazy holder of two values - * - * Lazy variant of {@link IPair} - * - * @author ben - * - * @param - * The type of value stored on the left side of the pair - * @param - * The type of value stored on the right side of the pair - */ -public class LazyPair implements IPair, ILazy { - /** - * The backing store for this pair - */ - protected IHolder> delegatePair; - - private boolean materialized = false; - private boolean pendingActions = false; - - /** - * Create a new blank lazy pair - */ - public LazyPair() { - delegatePair = new LazyHolder<>(new Pair<>()); - } - - /** - * Create a new lazy pair with the specified initial values - * - * @param leftValue - * The initial value for the left side of the pair - * @param rightValue - * The initial value for the right side of the pair - */ - public LazyPair(L leftValue, R rightValue) { - materialized = true; - - delegatePair = new LazyHolder<>(new Pair<>(leftValue, rightValue)); - } - - /** - * Create a new lazy pair with the specified sources for initial values - * - * @param leftValueSource - * The function to call for the left initial value - * @param rightValueSource - * The function to call for the right initial value - */ - public LazyPair(Supplier leftValueSource, - Supplier rightValueSource) { - if (leftValueSource == null || rightValueSource == null) { - throw new NullPointerException("Sources must be non-null"); - } - - delegatePair = new LazyHolder<>(() -> { - return new Pair<>(leftValueSource.get(), - rightValueSource.get()); - }); - } - - /** - * Create a new lazy pair with a specified internal delegate - * - * @param delegate - * The internal delegate for the pair - */ - private LazyPair(IHolder> delegate, boolean mater, - boolean pend) { - materialized = mater; - pendingActions = pend; - - delegatePair = delegate; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer) - */ - @Override - public void doWith(BiConsumer action) { - if (action == null) { - throw new NullPointerException("Action must be non-null"); - } - - pendingActions = true; - - delegatePair.doWith((currentPair) -> { - currentPair.doWith(action); - }); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.data.IPair#merge(java.util.function.BiFunction) - */ - @Override - public E merge(BiFunction merger) { - if (merger == null) { - throw new NullPointerException("Merger must be non-null"); - } - - materialized = true; - pendingActions = false; - - return delegatePair - .unwrap((currentPair) -> currentPair.merge(merger)); - } - - @Override - public boolean isMaterialized() { - return materialized; - } - - @Override - public boolean hasPendingActions() { - return pendingActions; - } - - /* - * Note: Materializing will also apply all currently pending actions - */ - @Override - public void materialize() { - merge((left, right) -> null); - - materialized = true; - pendingActions = false; - } - - @Override - public void applyPendingActions() { - merge((left, right) -> null); - - materialized = true; - pendingActions = false; - } - - @Override - public IPair bind( - BiFunction> binder) { - IHolder> newDelegate = delegatePair - .map((pairVal) -> { - return pairVal.bind(binder); - }); - - return new LazyPair<>(newDelegate, isMaterialized(), - hasPendingActions()); - } - - @Override - public String toString() { - return delegatePair.toString(); - } -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java deleted file mode 100644 index 4bd3832..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java +++ /dev/null @@ -1,202 +0,0 @@ -package bjc.utils.data.lazy; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Supplier; - -import bjc.utils.data.GenHolder; -import bjc.utils.data.IPair; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IFunctionalList; - -/** - * New implementation of lazy pair not delegating to {@link LazyHolder} - * - * @author ben - * @param - * The type on the left side of the pair - * @param - * The type on the right side of the pair - * - */ -public class NewLazyPair implements IPair, ILazy { - private static class BoundLazyPair - implements IPair { - private Supplier oldLeftSupplier; - private Supplier oldRightSupplier; - - private BiFunction> newPairSupplier; - - private IPair newPair; - - private boolean newPairMaterialized; - - public BoundLazyPair(Supplier leftSup, - Supplier rightSup, - BiFunction> binder) { - oldLeftSupplier = leftSup; - oldRightSupplier = rightSup; - - newPairSupplier = binder; - } - - @Override - public IPair bind( - BiFunction> binder) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void doWith(BiConsumer action) { - // TODO Auto-generated method stub - - } - - @Override - public E merge(BiFunction merger) { - if (!newPairMaterialized) { - newPair = newPairSupplier.apply(oldLeftSupplier.get(), - oldRightSupplier.get()); - } - - return newPair.merge(merger); - } - } - - private L leftValue; - private R rightValue; - - private Supplier rightValueSupplier; - private Supplier leftValueSupplier; - - private boolean rightMaterialized; - private boolean leftMaterialized; - - private IFunctionalList> actions; - - /** - * Create a new lazy pair - * - * @param leftVal - * The left value in the pair - * @param rightVal - * The right value in the pair - */ - public NewLazyPair(L leftVal, R rightVal) { - leftValueSupplier = () -> leftVal; - rightValueSupplier = () -> rightVal; - } - - /** - * Create a new lazy pair - * - * @param leftSupplier - * The supplier for the left value in the pair - * @param rightSupplier - * The supplier for the right value in the pair - */ - public NewLazyPair(Supplier leftSupplier, - Supplier rightSupplier) { - leftValueSupplier = leftSupplier; - rightValueSupplier = rightSupplier; - } - - @Override - public void applyPendingActions() { - if (!isMaterialized()) { - throw new UnsupportedOperationException( - "Can only apply actions to materialized values"); - } - - actions.forEach((action) -> { - action.accept(leftValue, rightValue); - }); - - actions = new FunctionalList<>(); - } - - private void applyPossiblyPendingActions(GenHolder hasActions, - IFunctionalList> pendingActions) { - if (hasActions.unwrap((val) -> val) == true) { - pendingActions.forEach((action) -> { - action.accept(leftValue, rightValue); - }); - - hasActions.transform((val) -> false); - } - } - - @Override - public IPair bind( - BiFunction> binder) { - GenHolder hasActions = new GenHolder<>(true); - IFunctionalList> pendingActions = new FunctionalList<>(); - - actions.forEach(pendingActions::add); - - return new BoundLazyPair<>(() -> { - applyPossiblyPendingActions(hasActions, pendingActions); - - return leftValue; - }, () -> { - applyPossiblyPendingActions(hasActions, pendingActions); - - return rightValue; - }, binder); - } - - @Override - public void doWith(BiConsumer action) { - actions.add(action); - } - - @Override - public boolean hasPendingActions() { - return !actions.isEmpty(); - } - - @Override - public boolean isMaterialized() { - if (leftValueSupplier == null) { - if (rightValueSupplier == null) { - return true; - } - - return rightMaterialized; - } - - if (rightValueSupplier == null) { - return leftMaterialized; - } - - return leftMaterialized && rightMaterialized; - } - - @Override - public void materialize() { - if (isMaterialized()) { - throw new UnsupportedOperationException( - "Cannot materialize lazy object twice"); - } - - if (leftValueSupplier != null) { - leftValue = leftValueSupplier.get(); - } - - if (rightValueSupplier != null) { - rightValue = rightValueSupplier.get(); - } - } - - @Override - public E merge(BiFunction merger) { - if (!isMaterialized()) { - materialize(); - } - - applyPendingActions(); - - return merger.apply(leftValue, rightValue); - } -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java index 9574376..9b388b2 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java @@ -5,17 +5,16 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; -import java.util.Random; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; -import bjc.utils.data.GenHolder; -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; +import bjc.utils.data.experimental.IHolder; +import bjc.utils.data.experimental.IPair; +import bjc.utils.data.experimental.Identity; +import bjc.utils.data.experimental.Pair; import java.util.ArrayList; @@ -45,6 +44,8 @@ public class FunctionalList implements Cloneable, IFunctionalList { /** * Create a new functional list containing the specified items. * + * Takes O(n) time, where n is the number of items specified + * * @param items * The items to put into this functional list. */ @@ -70,6 +71,8 @@ public class FunctionalList implements Cloneable, IFunctionalList { /** * Create a new functional list as a wrapper of a existing list. * + * Takes O(1) time, since it doesn't copy the list. + * * @param backingList * The list to use as a backing list. */ @@ -82,7 +85,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { wrappedList = backingList; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#add(E) */ @Override @@ -90,8 +95,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return wrappedList.add(item); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#allMatch(java.util.function.Predicate) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#allMatch(java.util.function. + * Predicate) */ @Override public boolean allMatch(Predicate matchPredicate) { @@ -110,8 +118,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return true; } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#anyMatch(java.util.function.Predicate) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#anyMatch(java.util.function. + * Predicate) */ @Override public boolean anyMatch(Predicate matchPredicate) { @@ -130,6 +141,13 @@ public class FunctionalList implements Cloneable, IFunctionalList { return false; } + /** + * Clone this list into a new one, and clone the backing list as well + * + * Takes O(n) time, where n is the number of elements in the list + * + * @return A list + */ @Override public IFunctionalList clone() { IFunctionalList clonedList = new FunctionalList<>(); @@ -141,8 +159,12 @@ public class FunctionalList implements Cloneable, IFunctionalList { return clonedList; } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#combineWith(bjc.utils.funcdata.IFunctionalList, java.util.function.BiFunction) + /* + * (non-Javadoc) + * + * @see + * bjc.utils.funcdata.IFunctionalList#combineWith(bjc.utils.funcdata. + * IFunctionalList, java.util.function.BiFunction) */ @Override public IFunctionalList combineWith( @@ -173,7 +195,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return returnedList; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#contains(E) */ @Override @@ -182,7 +206,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return this.anyMatch(item::equals); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#first() */ @Override @@ -195,8 +221,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return wrappedList.get(0); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#flatMap(java.util.function.Function) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#flatMap(java.util.function. + * Function) */ @Override public IFunctionalList flatMap( @@ -224,8 +253,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return returnedList; } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#forEach(java.util.function.Consumer) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#forEach(java.util.function. + * Consumer) */ @Override public void forEach(Consumer action) { @@ -236,8 +268,12 @@ public class FunctionalList implements Cloneable, IFunctionalList { wrappedList.forEach(action); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#forEachIndexed(java.util.function.BiConsumer) + /* + * (non-Javadoc) + * + * @see + * bjc.utils.funcdata.IFunctionalList#forEachIndexed(java.util.function + * .BiConsumer) */ @Override public void forEachIndexed(BiConsumer indexedAction) { @@ -246,7 +282,7 @@ public class FunctionalList implements Cloneable, IFunctionalList { } // This is held b/c ref'd variables must be final/effectively final - GenHolder currentIndex = new GenHolder<>(0); + IHolder currentIndex = new Identity<>(0); wrappedList.forEach((element) -> { // Call the action with the index and the value @@ -258,7 +294,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { }); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#getByIndex(int) */ @Override @@ -275,8 +313,12 @@ public class FunctionalList implements Cloneable, IFunctionalList { return wrappedList; } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#getMatching(java.util.function.Predicate) + /* + * (non-Javadoc) + * + * @see + * bjc.utils.funcdata.IFunctionalList#getMatching(java.util.function. + * Predicate) */ @Override public IFunctionalList getMatching(Predicate matchPredicate) { @@ -296,7 +338,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return returnedList; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#getSize() */ @Override @@ -304,7 +348,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return wrappedList.size(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#isEmpty() */ @Override @@ -312,8 +358,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return wrappedList.isEmpty(); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#map(java.util.function.Function) + /* + * (non-Javadoc) + * + * @see + * bjc.utils.funcdata.IFunctionalList#map(java.util.function.Function) */ @Override public IFunctionalList map(Function elementTransformer) { @@ -332,8 +381,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return returnedList; } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#pairWith(bjc.utils.funcdata.IFunctionalList) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#pairWith(bjc.utils.funcdata. + * IFunctionalList) */ @Override public IFunctionalList> pairWith( @@ -341,7 +393,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return combineWith(rightList, Pair::new); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#partition(int) */ @Override @@ -357,7 +411,7 @@ public class FunctionalList implements Cloneable, IFunctionalList { IFunctionalList> returnedList = new FunctionalList<>(); // The current partition being filled - GenHolder> currentPartition = new GenHolder<>( + IHolder> currentPartition = new Identity<>( new FunctionalList<>()); this.forEach((element) -> { @@ -383,12 +437,14 @@ public class FunctionalList implements Cloneable, IFunctionalList { * Check if a partition has room for another item */ private Boolean isPartitionFull(int numberPerPartition, - GenHolder> currentPartition) { + IHolder> currentPartition) { return currentPartition.unwrap( (partition) -> partition.getSize() >= numberPerPartition); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#prepend(E) */ @Override @@ -396,23 +452,28 @@ public class FunctionalList implements Cloneable, IFunctionalList { wrappedList.add(0, item); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#randItem(java.util.Random) */ @Override - public E randItem(Random rnd) { + public E randItem(Function rnd) { if (rnd == null) { throw new NullPointerException( "Random source must not be null"); } - int randomIndex = rnd.nextInt(wrappedList.size()); + int randomIndex = rnd.apply(wrappedList.size()); return wrappedList.get(randomIndex); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#reduceAux(T, java.util.function.BiFunction, java.util.function.Function) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#reduceAux(T, + * java.util.function.BiFunction, java.util.function.Function) */ @Override public F reduceAux(T initialValue, @@ -425,7 +486,7 @@ public class FunctionalList implements Cloneable, IFunctionalList { } // The current collapsed list - IHolder currentState = new GenHolder<>(initialValue); + IHolder currentState = new Identity<>(initialValue); wrappedList.forEach(element -> { // Accumulate a new value into the state @@ -437,8 +498,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { return currentState.unwrap(resultTransformer); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#removeIf(java.util.function.Predicate) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#removeIf(java.util.function. + * Predicate) */ @Override public boolean removeIf(Predicate removePredicate) { @@ -449,7 +513,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return wrappedList.removeIf(removePredicate); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#removeMatching(E) */ @Override @@ -457,8 +523,11 @@ public class FunctionalList implements Cloneable, IFunctionalList { removeIf((element) -> element.equals(desiredElement)); } - /* (non-Javadoc) - * @see bjc.utils.funcdata.IFunctionalList#search(E, java.util.Comparator) + /* + * (non-Javadoc) + * + * @see bjc.utils.funcdata.IFunctionalList#search(E, + * java.util.Comparator) */ @Override public E search(E searchKey, Comparator comparator) { @@ -475,7 +544,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return null; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#sort(java.util.Comparator) */ @Override @@ -483,7 +554,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { Collections.sort(wrappedList, comparator); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see bjc.utils.funcdata.IFunctionalList#toIterable() */ @Override @@ -512,4 +585,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { return sb.toString(); } + + @Override + public E[] toArray(E[] arrType) { + return wrappedList.toArray(arrType); + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java index b505ebd..da30064 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java @@ -6,7 +6,7 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; -import bjc.utils.data.Pair; +import bjc.utils.data.experimental.IPair; /** * Basic implementation of {@link IFunctionalMap} @@ -102,6 +102,11 @@ public class FunctionalMap implements IFunctionalMap { action.accept(transformer.apply(val)); }); } + + @Override + public IFunctionalList valueList() { + return mapToTransform.valueList().map(transformer); + } } private Map wrappedMap; @@ -134,10 +139,10 @@ public class FunctionalMap implements IFunctionalMap { * The entries to put into the map */ @SafeVarargs - public FunctionalMap(Pair... entries) { + public FunctionalMap(IPair... entries) { this(); - for (Pair entry : entries) { + for (IPair entry : entries) { entry.doWith((key, val) -> { wrappedMap.put(key, val); }); @@ -243,4 +248,15 @@ public class FunctionalMap implements IFunctionalMap { public void forEachValue(Consumer action) { wrappedMap.values().forEach(action); } + + @Override + public IFunctionalList valueList() { + FunctionalList values = new FunctionalList<>(); + + wrappedMap.values().forEach((value) -> { + values.add(value); + }); + + return values; + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java index a017aa9..949fc33 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java @@ -1,20 +1,22 @@ package bjc.utils.funcdata; import java.util.Comparator; -import java.util.Random; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; -import bjc.utils.data.IPair; +import bjc.utils.data.experimental.IPair; /** * A wrapper over another list that provides eager functional operations * over it. Differs from a stream in every way except for the fact that * they both provide functional operations. * + * NOTE: The indications of complexity for methods assume that the backing + * list has performance on the order of an array + * * @author ben * * @param @@ -25,6 +27,8 @@ public interface IFunctionalList { /** * Add an item to this list * + * Takes O(1) time. + * * @param item * The item to add to this list. * @return Whether the item was added to the list succesfully. @@ -35,6 +39,10 @@ public interface IFunctionalList { * Check if all of the elements of this list match the specified * predicate. * + * Takes O(f * p(n)) time on average, where f is defined as the average + * number of elements in a list until the predicate returns false, and + * p is the average running time of the predicate + * * @param matchPredicate * The predicate to use for checking. * @return Whether all of the elements of the list match the specified @@ -45,6 +53,10 @@ public interface IFunctionalList { /** * Check if any of the elements in this list match the specified list. * + * Takes O(f * p(n)) time on average, where f is defined as the average + * number of elements in a list until the predicate returns true, and p + * is the average running time of the predicate + * * @param matchPredicate * The predicate to use for checking. * @return Whether any element in the list matches the provided @@ -60,6 +72,10 @@ public interface IFunctionalList { * NOTE: The returned list will have the length of the shorter of this * list and the combined one. * + * Takes O(q * c(q)), where q is defined as the length of the shorter + * of this list and the provided one, and c is the running time of the + * combiner. + * * @param * The type of the second list * @param @@ -77,6 +93,8 @@ public interface IFunctionalList { /** * Check if the list contains the specified item * + * Takes O(n) time, assuming object compare in constant time. + * * @param item * The item to see if it is contained * @return Whether or not the specified item is in the list @@ -86,6 +104,8 @@ public interface IFunctionalList { /** * Get the first element in the list * + * Takes O(1) time + * * @return The first element in this list. */ E first(); @@ -94,6 +114,9 @@ public interface IFunctionalList { * Apply a function to each member of the list, then flatten the * results. Does not change the underlying list. * + * Takes O(n * m) time, where m is the average number of elements in + * the returned list. + * * @param * The type of the flattened list * @@ -108,6 +131,9 @@ public interface IFunctionalList { /** * Apply a given action for each member of the list * + * Takes O(n * f(n)) time, where n is the length of the list, and f is + * the running time of the action. + * * @param action * The action to apply to each member of the list. */ @@ -116,6 +142,9 @@ public interface IFunctionalList { /** * Apply a given function to each element in the list and its index. * + * Takes O(n * f(n)) time, where n is the length of the list, and f is + * the running time of the action. + * * @param indexedAction * The function to apply to each element in the list and its * index. @@ -125,6 +154,8 @@ public interface IFunctionalList { /** * Retrieve a value in the list by its index. * + * Takes O(1) time. + * * @param index * The index to retrieve a value from. * @return The value at the specified index in the list. @@ -134,6 +165,7 @@ public interface IFunctionalList { /** * Retrieve a list containing all elements matching a predicate * + * Takes O(n) time, where n is the number of elements in the list * @param matchPredicate * The predicate to match by * @return A list containing all elements that match the predicate @@ -206,7 +238,7 @@ public interface IFunctionalList { * The random number generator to use. * @return A random element from this list. */ - E randItem(Random rnd); + E randItem(Function rnd); /** * Reduce this list to a single value, using a accumulative approach. @@ -278,4 +310,13 @@ public interface IFunctionalList { * @return An iterable view onto the list */ Iterable toIterable(); + + /** + * Convert this list into an array + * + * @param arrType + * The type of array to return + * @return The list, as an array + */ + E[] toArray(E[] arrType); } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java index e089850..c879229 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java @@ -118,4 +118,11 @@ public interface IFunctionalMap { * The action to perform on each value in the map */ void forEachValue(Consumer action); + + /** + * Get a list of the values in this map + * + * @return A list of values in this map + */ + IFunctionalList valueList(); } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java index f490727..3374aa2 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java @@ -28,7 +28,7 @@ public class EnumUtils { Random rnd) { E[] enumValues = enumClass.getEnumConstants(); - return new FunctionalList<>(enumValues).randItem(rnd); + return new FunctionalList<>(enumValues).randItem(rnd::nextInt); } /** @@ -54,7 +54,7 @@ public class EnumUtils { int randomValueCount = enumValues.length - nValues; for (int i = 0; i <= randomValueCount; i++) { - E rDir = valueList.randItem(rnd); + E rDir = valueList.randItem(rnd::nextInt); valueList.removeMatching(rDir); } diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java index 871e1cf..132e4c5 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java @@ -1,5 +1,6 @@ package bjc.utils.funcutils; +import java.util.ArrayList; import java.util.Deque; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -20,8 +21,8 @@ import bjc.utils.funcdata.IFunctionalList; public class ListUtils { private static final int MAX_NTRIESPART = 50; - private static final class TokenDeaffixer - implements BiFunction> { + private static final class TokenDeaffixer implements + BiFunction> { private String token; public TokenDeaffixer(String tok) { @@ -53,8 +54,8 @@ public class ListUtils { } } - private static final class TokenSplitter - implements BiFunction> { + private static final class TokenSplitter implements + BiFunction> { private String tokenToSplit; public TokenSplitter(String tok) { @@ -351,4 +352,71 @@ public class ListUtils { }); } } + + /** + * Select a number of random items from the list, with replacement + * + * @param + * The type of items to select + * @param list + * The list to select from + * @param numberOfItems + * The number of items to selet + * @param rng + * 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 + */ + public static IFunctionalList drawWithReplacement( + IFunctionalList list, int numberOfItems, + Function rng) { + IFunctionalList selectedItems = new FunctionalList<>( + new ArrayList<>(numberOfItems)); + + for (int i = 0; i < numberOfItems; i++) { + selectedItems.add(list.randItem(rng)); + } + + return selectedItems; + } + + /** + * Select a number of random items from the list without replacement + * + * @param + * The type of items to select + * @param list + * The list to select from + * @param numberOfItems + * The number of items to selet + * @param rng + * 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 + */ + + public static IFunctionalList drawWithoutReplacement( + IFunctionalList list, int numberOfItems, + Function rng) { + IFunctionalList selectedItems = new FunctionalList<>( + new ArrayList<>(numberOfItems)); + + int totalItems = list.getSize(); + + list.forEachIndexed((index, element) -> { + int winningChance = numberOfItems - selectedItems.getSize(); + // n - m + int totalChance = totalItems - (index - 1); + // N - t + + // Probability of selecting the t+1'th element + if (NumberUtils.isProbable(winningChance, totalChance, rng)) { + selectedItems.add(element); + } + }); + + return selectedItems; + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java new file mode 100644 index 0000000..1f8f61d --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java @@ -0,0 +1,53 @@ +package bjc.utils.funcutils; + +import java.util.function.Function; + +/** + * Utility functions for dealing with numbers + * + * @author ben + * + */ +public class NumberUtils { + /** + * Compute the falling factorial of a number + * + * @param value + * The number to compute + * @param power + * The power to do the falling factorial for + * @return The falling factorial of the number to the power + */ + public static int fallingFactorial(int value, int power) { + if (power == 0) { + return 1; + } else if (power == 1) { + return value; + } else { + int result = 1; + + for (int currentSub = 0; currentSub < power + + 1; currentSub++) { + result *= value - currentSub; + } + + return result; + } + } + + /** + * Evaluates a linear probability distribution + * + * @param topExp + * The number of winning possibilities + * @param bottomExp + * The number of total possibilities + * @param rng + * The function to use to generate a random possibility + * @return Whether or not a random possibility was a winning one + */ + public static boolean isProbable(int topExp, int bottomExp, + Function rng) { + return rng.apply(bottomExp) < topExp; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java index 10da34e..f10ee26 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java +++ b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java @@ -1,11 +1,12 @@ package bjc.utils.gen; import java.util.Random; + +import bjc.utils.data.experimental.IHolder; +import bjc.utils.data.experimental.IPair; +import bjc.utils.data.experimental.Identity; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.IFunctionalList; -import bjc.utils.data.GenHolder; -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; /** * Represents a random number generator where certain results are weighted @@ -25,14 +26,14 @@ public class WeightedRandom { /** * The list of possible results to pick from */ - private IFunctionalList results; + private IFunctionalList results; /** * The source for any needed random numbers */ - private Random source; + private Random source; - private int totalChance; + private int totalChance; /** * Create a new weighted random generator with the specified source of @@ -74,10 +75,10 @@ public class WeightedRandom { * @return A random value selected in a weighted fashion. */ public E generateValue() { - GenHolder randomValue = - new GenHolder<>(source.nextInt(totalChance)); - IHolder currentResult = new GenHolder<>(); - GenHolder valuePicked = new GenHolder<>(true); + IHolder randomValue = new Identity<>( + source.nextInt(totalChance)); + IHolder currentResult = new Identity<>(); + IHolder valuePicked = new Identity<>(true); probabilities.forEachIndexed((itemIndex, itemProbability) -> { if (valuePicked.unwrap(bool -> bool)) { -- cgit v1.2.3