diff --git a/src/main/java/baritone/builder/utils/com/github/btrekkie/red_black_node/RedBlackNode.java b/src/main/java/baritone/builder/utils/com/github/btrekkie/red_black_node/RedBlackNode.java
deleted file mode 100644
index 5c952961c..000000000
--- a/src/main/java/baritone/builder/utils/com/github/btrekkie/red_black_node/RedBlackNode.java
+++ /dev/null
@@ -1,1411 +0,0 @@
-/*
- * This file was originally written by btrekkie under the MIT license, which is compatible with the LGPL license for this usage within Baritone
- * https://github.com/btrekkie/RedBlackNode/blob/master/src/main/java/com/github/btrekkie/red_black_node/RedBlackNode.java
- */
-
-package baritone.builder.utils.com.github.btrekkie.red_black_node;
-
-import java.lang.reflect.Array;
-import java.util.*;
-
-/**
- * A node in a red-black tree ( https://en.wikipedia.org/wiki/Red%E2%80%93black_tree ). Compared to a class like Java's
- * TreeMap, RedBlackNode is a low-level data structure. The internals of a node are exposed as public fields, allowing
- * clients to directly observe and manipulate the structure of the tree. This gives clients flexibility, although it
- * also enables them to violate the red-black or BST properties. The RedBlackNode class provides methods for performing
- * various standard operations, such as insertion and removal.
- *
- * Unlike most implementations of binary search trees, RedBlackNode supports arbitrary augmentation. By subclassing
- * RedBlackNode, clients can add arbitrary data and augmentation information to each node. For example, if we were to
- * use a RedBlackNode subclass to implement a sorted set, the subclass would have a field storing an element in the set.
- * If we wanted to keep track of the number of non-leaf nodes in each subtree, we would store this as a "size" field and
- * override augment() to update this field. All RedBlackNode methods (such as "insert" and remove()) call augment() as
- * necessary to correctly maintain the augmentation information, unless otherwise indicated.
- *
- * The values of the tree are stored in the non-leaf nodes. RedBlackNode does not support use cases where values must be
- * stored in the leaf nodes. It is recommended that all of the leaf nodes in a given tree be the same (black)
- * RedBlackNode instance, to save space. The root of an empty tree is a leaf node, as opposed to null.
- *
- * For reference, a red-black tree is a binary search tree satisfying the following properties:
- *
- * - Every node is colored red or black.
- * - The leaf nodes, which are dummy nodes that do not store any values, are colored black.
- * - The root is black.
- * - Both children of each red node are black.
- * - Every path from the root to a leaf contains the same number of black nodes.
- *
- * @param The type of node in the tree. For example, we might have
- * "class FooNode extends RedBlackNode>".
- * @author Bill Jacobs
- */
-public abstract class RedBlackNode> implements Comparable {
- /**
- * A Comparator that compares Comparable elements using their natural order.
- */
- private static final Comparator> NATURAL_ORDER = new Comparator>() {
- @Override
- public int compare(Comparable value1, Comparable value2) {
- return value1.compareTo(value2);
- }
- };
-
- /**
- * The parent of this node, if any. "parent" is null if this is a leaf node.
- */
- public N parent;
-
- /**
- * The left child of this node. "left" is null if this is a leaf node.
- */
- public N left;
-
- /**
- * The right child of this node. "right" is null if this is a leaf node.
- */
- public N right;
-
- /**
- * Whether the node is colored red, as opposed to black.
- */
- public boolean isRed;
-
- /**
- * Sets any augmentation information about the subtree rooted at this node that is stored in this node. For
- * example, if we augment each node by subtree size (the number of non-leaf nodes in the subtree), this method would
- * set the size field of this node to be equal to the size field of the left child plus the size field of the right
- * child plus one.
- *
- * "Augmentation information" is information that we can compute about a subtree rooted at some node, preferably
- * based only on the augmentation information in the node's two children and the information in the node. Examples
- * of augmentation information are the sum of the values in a subtree and the number of non-leaf nodes in a subtree.
- * Augmentation information may not depend on the colors of the nodes.
- *
- * This method returns whether the augmentation information in any of the ancestors of this node might have been
- * affected by changes in this subtree since the last call to augment(). In the usual case, where the augmentation
- * information depends only on the information in this node and the augmentation information in its immediate
- * children, this is equivalent to whether the augmentation information changed as a result of this call to
- * augment(). For example, in the case of subtree size, this returns whether the value of the size field prior to
- * calling augment() differed from the size field of the left child plus the size field of the right child plus one.
- * False positives are permitted. The return value is unspecified if we have not called augment() on this node
- * before.
- *
- * This method may assume that this is not a leaf node. It may not assume that the augmentation information stored
- * in any of the tree's nodes is correct. However, if the augmentation information stored in all of the node's
- * descendants is correct, then the augmentation information stored in this node must be correct after calling
- * augment().
- */
- public boolean augment() {
- return false;
- }
-
- /**
- * Throws a RuntimeException if we detect that this node locally violates any invariants specific to this subclass
- * of RedBlackNode. For example, if this stores the size of the subtree rooted at this node, this should throw a
- * RuntimeException if the size field of this is not equal to the size field of the left child plus the size field
- * of the right child plus one. Note that we may call this on a leaf node.
- *
- * assertSubtreeIsValid() calls assertNodeIsValid() on each node, or at least starts to do so until it detects a
- * problem. assertNodeIsValid() should assume the node is in a tree that satisfies all properties common to all
- * red-black trees, as assertSubtreeIsValid() is responsible for such checks. assertNodeIsValid() should be
- * "downward-looking", i.e. it should ignore any information in "parent", and it should be "local", i.e. it should
- * only check a constant number of descendants. To include "global" checks, such as verifying the BST property
- * concerning ordering, override assertSubtreeIsValid(). assertOrderIsValid is useful for checking the BST
- * property.
- */
- public void assertNodeIsValid() {
-
- }
-
- /**
- * Returns whether this is a leaf node.
- */
- public boolean isLeaf() {
- return left == null;
- }
-
- /**
- * Returns the root of the tree that contains this node.
- */
- public N root() {
- @SuppressWarnings("unchecked")
- N node = (N) this;
- while (node.parent != null) {
- node = node.parent;
- }
- return node;
- }
-
- /**
- * Returns the first node in the subtree rooted at this node, if any.
- */
- public N min() {
- if (isLeaf()) {
- return null;
- }
- @SuppressWarnings("unchecked")
- N node = (N) this;
- while (!node.left.isLeaf()) {
- node = node.left;
- }
- return node;
- }
-
- /**
- * Returns the last node in the subtree rooted at this node, if any.
- */
- public N max() {
- if (isLeaf()) {
- return null;
- }
- @SuppressWarnings("unchecked")
- N node = (N) this;
- while (!node.right.isLeaf()) {
- node = node.right;
- }
- return node;
- }
-
- /**
- * Returns the node immediately before this in the tree that contains this node, if any.
- */
- public N predecessor() {
- if (!left.isLeaf()) {
- N node;
- for (node = left; !node.right.isLeaf(); node = node.right) ;
- return node;
- } else if (parent == null) {
- return null;
- } else {
- @SuppressWarnings("unchecked")
- N node = (N) this;
- while (node.parent != null && node.parent.left == node) {
- node = node.parent;
- }
- return node.parent;
- }
- }
-
- /**
- * Returns the node immediately after this in the tree that contains this node, if any.
- */
- public N successor() {
- if (!right.isLeaf()) {
- N node;
- for (node = right; !node.left.isLeaf(); node = node.left) ;
- return node;
- } else if (parent == null) {
- return null;
- } else {
- @SuppressWarnings("unchecked")
- N node = (N) this;
- while (node.parent != null && node.parent.right == node) {
- node = node.parent;
- }
- return node.parent;
- }
- }
-
- /**
- * Performs a left rotation about this node. This method assumes that !isLeaf() && !right.isLeaf(). It calls
- * augment() on this node and on its resulting parent. However, it does not call augment() on any of the resulting
- * parent's ancestors, because that is normally the responsibility of the caller.
- *
- * @return The return value from calling augment() on the resulting parent.
- */
- public boolean rotateLeft() {
- if (isLeaf() || right.isLeaf()) {
- throw new IllegalArgumentException("The node or its right child is a leaf");
- }
- N newParent = right;
- right = newParent.left;
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- if (!right.isLeaf()) {
- right.parent = nThis;
- }
- newParent.parent = parent;
- parent = newParent;
- newParent.left = nThis;
- if (newParent.parent != null) {
- if (newParent.parent.left == this) {
- newParent.parent.left = newParent;
- } else {
- newParent.parent.right = newParent;
- }
- }
- augment();
- return newParent.augment();
- }
-
- /**
- * Performs a right rotation about this node. This method assumes that !isLeaf() && !left.isLeaf(). It calls
- * augment() on this node and on its resulting parent. However, it does not call augment() on any of the resulting
- * parent's ancestors, because that is normally the responsibility of the caller.
- *
- * @return The return value from calling augment() on the resulting parent.
- */
- public boolean rotateRight() {
- if (isLeaf() || left.isLeaf()) {
- throw new IllegalArgumentException("The node or its left child is a leaf");
- }
- N newParent = left;
- left = newParent.right;
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- if (!left.isLeaf()) {
- left.parent = nThis;
- }
- newParent.parent = parent;
- parent = newParent;
- newParent.right = nThis;
- if (newParent.parent != null) {
- if (newParent.parent.left == this) {
- newParent.parent.left = newParent;
- } else {
- newParent.parent.right = newParent;
- }
- }
- augment();
- return newParent.augment();
- }
-
- /**
- * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements
- * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be
- * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs
- * any rotations by calling rotateLeft() and rotateRight(). This method is more efficient than fixInsertion if
- * "augment" is false or augment() might return false.
- *
- * @param augment Whether to set the augmentation information for "node" and its ancestors, by calling augment().
- */
- public void fixInsertionWithoutGettingRoot(boolean augment) {
- if (!isRed) {
- throw new IllegalArgumentException("The node must be red");
- }
- boolean changed = augment;
- if (augment) {
- augment();
- }
-
- RedBlackNode node = this;
- while (node.parent != null && node.parent.isRed) {
- N parent = node.parent;
- N grandparent = parent.parent;
- if (grandparent.left.isRed && grandparent.right.isRed) {
- grandparent.left.isRed = false;
- grandparent.right.isRed = false;
- grandparent.isRed = true;
-
- if (changed) {
- changed = parent.augment();
- if (changed) {
- changed = grandparent.augment();
- }
- }
- node = grandparent;
- } else {
- if (parent.left == node) {
- if (grandparent.right == parent) {
- parent.rotateRight();
- node = parent;
- parent = node.parent;
- }
- } else if (grandparent.left == parent) {
- parent.rotateLeft();
- node = parent;
- parent = node.parent;
- }
-
- if (parent.left == node) {
- boolean grandparentChanged = grandparent.rotateRight();
- if (augment) {
- changed = grandparentChanged;
- }
- } else {
- boolean grandparentChanged = grandparent.rotateLeft();
- if (augment) {
- changed = grandparentChanged;
- }
- }
-
- parent.isRed = false;
- grandparent.isRed = true;
- node = parent;
- break;
- }
- }
-
- if (node.parent == null) {
- node.isRed = false;
- }
- if (changed) {
- for (node = node.parent; node != null; node = node.parent) {
- if (!node.augment()) {
- break;
- }
- }
- }
- }
-
- /**
- * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements
- * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be
- * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs
- * any rotations by calling rotateLeft() and rotateRight(). This method is more efficient than fixInsertion() if
- * augment() might return false.
- */
- public void fixInsertionWithoutGettingRoot() {
- fixInsertionWithoutGettingRoot(true);
- }
-
- /**
- * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements
- * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be
- * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs
- * any rotations by calling rotateLeft() and rotateRight().
- *
- * @param augment Whether to set the augmentation information for "node" and its ancestors, by calling augment().
- * @return The root of the resulting tree.
- */
- public N fixInsertion(boolean augment) {
- fixInsertionWithoutGettingRoot(augment);
- return root();
- }
-
- /**
- * Performs red-black insertion fixup. To be more precise, this fixes a tree that satisfies all of the requirements
- * of red-black trees, except that this may be a red child of a red node, and if this is the root, the root may be
- * red. node.isRed must initially be true. This method assumes that this is not a leaf node. The method performs
- * any rotations by calling rotateLeft() and rotateRight().
- *
- * @return The root of the resulting tree.
- */
- public N fixInsertion() {
- fixInsertionWithoutGettingRoot(true);
- return root();
- }
-
- /**
- * Returns a Comparator that compares instances of N using their natural order, as in N.compareTo.
- */
- @SuppressWarnings({"rawtypes", "unchecked"})
- private Comparator naturalOrder() {
- Comparator comparator = (Comparator) NATURAL_ORDER;
- return (Comparator) comparator;
- }
-
- /**
- * Inserts the specified node into the tree rooted at this node. Assumes this is the root. We treat newNode as a
- * solitary node that does not belong to any tree, and we ignore its initial "parent", "left", "right", and isRed
- * fields.
- *
- * If it is not efficient or convenient to find the location for a node using a Comparator, then you should manually
- * add the node to the appropriate location, color it red, and call fixInsertion().
- *
- * @param newNode The node to insert.
- * @param allowDuplicates Whether to insert newNode if there is an equal node in the tree. To check whether we
- * inserted newNode, check whether newNode.parent is null and the return value differs from newNode.
- * @param comparator A comparator indicating where to put the node. If this is null, we use the nodes' natural
- * order, as in N.compareTo. If you are passing null, then you must override the compareTo method, because the
- * default implementation requires the nodes to already be in the same tree.
- * @return The root of the resulting tree.
- */
- public N insert(N newNode, boolean allowDuplicates, Comparator super N> comparator) {
- if (parent != null) {
- throw new IllegalArgumentException("This is not the root of a tree");
- }
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- if (isLeaf()) {
- newNode.isRed = false;
- newNode.left = nThis;
- newNode.right = nThis;
- newNode.parent = null;
- newNode.augment();
- return newNode;
- }
- if (comparator == null) {
- comparator = naturalOrder();
- }
-
- N node = nThis;
- int comparison;
- while (true) {
- comparison = comparator.compare(newNode, node);
- if (comparison < 0) {
- if (!node.left.isLeaf()) {
- node = node.left;
- } else {
- newNode.left = node.left;
- newNode.right = node.left;
- node.left = newNode;
- newNode.parent = node;
- break;
- }
- } else if (comparison > 0 || allowDuplicates) {
- if (!node.right.isLeaf()) {
- node = node.right;
- } else {
- newNode.left = node.right;
- newNode.right = node.right;
- node.right = newNode;
- newNode.parent = node;
- break;
- }
- } else {
- newNode.parent = null;
- return nThis;
- }
- }
- newNode.isRed = true;
- return newNode.fixInsertion();
- }
-
- /**
- * Moves this node to its successor's former position in the tree and vice versa, i.e. sets the "left", "right",
- * "parent", and isRed fields of each. This method assumes that this is not a leaf node.
- *
- * @return The node with which we swapped.
- */
- private N swapWithSuccessor() {
- N replacement = successor();
- boolean oldReplacementIsRed = replacement.isRed;
- N oldReplacementLeft = replacement.left;
- N oldReplacementRight = replacement.right;
- N oldReplacementParent = replacement.parent;
-
- replacement.isRed = isRed;
- replacement.left = left;
- replacement.right = right;
- replacement.parent = parent;
- if (parent != null) {
- if (parent.left == this) {
- parent.left = replacement;
- } else {
- parent.right = replacement;
- }
- }
-
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- isRed = oldReplacementIsRed;
- left = oldReplacementLeft;
- right = oldReplacementRight;
- if (oldReplacementParent == this) {
- parent = replacement;
- parent.right = nThis;
- } else {
- parent = oldReplacementParent;
- parent.left = nThis;
- }
-
- replacement.right.parent = replacement;
- if (!replacement.left.isLeaf()) {
- replacement.left.parent = replacement;
- }
- if (!right.isLeaf()) {
- right.parent = nThis;
- }
- return replacement;
- }
-
- /**
- * Performs red-black deletion fixup. To be more precise, this fixes a tree that satisfies all of the requirements
- * of red-black trees, except that all paths from the root to a leaf that pass through the sibling of this node have
- * one fewer black node than all other root-to-leaf paths. This method assumes that this is not a leaf node.
- */
- private void fixSiblingDeletion() {
- RedBlackNode sibling = this;
- boolean changed = true;
- boolean haveAugmentedParent = false;
- boolean haveAugmentedGrandparent = false;
- while (true) {
- N parent = sibling.parent;
- if (sibling.isRed) {
- parent.isRed = true;
- sibling.isRed = false;
- if (parent.left == sibling) {
- changed = parent.rotateRight();
- sibling = parent.left;
- } else {
- changed = parent.rotateLeft();
- sibling = parent.right;
- }
- haveAugmentedParent = true;
- haveAugmentedGrandparent = true;
- } else if (!sibling.left.isRed && !sibling.right.isRed) {
- sibling.isRed = true;
- if (parent.isRed) {
- parent.isRed = false;
- break;
- } else {
- if (changed && !haveAugmentedParent) {
- changed = parent.augment();
- }
- N grandparent = parent.parent;
- if (grandparent == null) {
- break;
- } else if (grandparent.left == parent) {
- sibling = grandparent.right;
- } else {
- sibling = grandparent.left;
- }
- haveAugmentedParent = haveAugmentedGrandparent;
- haveAugmentedGrandparent = false;
- }
- } else {
- if (sibling == parent.left) {
- if (!sibling.left.isRed) {
- sibling.rotateLeft();
- sibling = sibling.parent;
- }
- } else if (!sibling.right.isRed) {
- sibling.rotateRight();
- sibling = sibling.parent;
- }
- sibling.isRed = parent.isRed;
- parent.isRed = false;
- if (sibling == parent.left) {
- sibling.left.isRed = false;
- changed = parent.rotateRight();
- } else {
- sibling.right.isRed = false;
- changed = parent.rotateLeft();
- }
- haveAugmentedParent = haveAugmentedGrandparent;
- haveAugmentedGrandparent = false;
- break;
- }
- }
-
- // Update augmentation info
- N parent = sibling.parent;
- if (changed && parent != null) {
- if (!haveAugmentedParent) {
- changed = parent.augment();
- }
- if (changed && parent.parent != null) {
- parent = parent.parent;
- if (!haveAugmentedGrandparent) {
- changed = parent.augment();
- }
- if (changed) {
- for (parent = parent.parent; parent != null; parent = parent.parent) {
- if (!parent.augment()) {
- break;
- }
- }
- }
- }
- }
- }
-
- /**
- * Removes this node from the tree that contains it. The effect of this method on the fields of this node is
- * unspecified. This method assumes that this is not a leaf node. This method is more efficient than remove() if
- * augment() might return false.
- *
- * If the node has two children, we begin by moving the node's successor to its former position, by changing the
- * successor's "left", "right", "parent", and isRed fields.
- */
- public void removeWithoutGettingRoot() {
- if (isLeaf()) {
- throw new IllegalArgumentException("Attempted to remove a leaf node");
- }
- N replacement;
- if (left.isLeaf() || right.isLeaf()) {
- replacement = null;
- } else {
- replacement = swapWithSuccessor();
- }
-
- N child;
- if (!left.isLeaf()) {
- child = left;
- } else if (!right.isLeaf()) {
- child = right;
- } else {
- child = null;
- }
-
- if (child != null) {
- // Replace this node with its child
- child.parent = parent;
- if (parent != null) {
- if (parent.left == this) {
- parent.left = child;
- } else {
- parent.right = child;
- }
- }
- child.isRed = false;
-
- if (child.parent != null) {
- N parent;
- for (parent = child.parent; parent != null; parent = parent.parent) {
- if (!parent.augment()) {
- break;
- }
- }
- }
- } else if (parent != null) {
- // Replace this node with a leaf node
- N leaf = left;
- N parent = this.parent;
- N sibling;
- if (parent.left == this) {
- parent.left = leaf;
- sibling = parent.right;
- } else {
- parent.right = leaf;
- sibling = parent.left;
- }
-
- if (!isRed) {
- RedBlackNode siblingNode = sibling;
- siblingNode.fixSiblingDeletion();
- } else {
- while (parent != null) {
- if (!parent.augment()) {
- break;
- }
- parent = parent.parent;
- }
- }
- }
-
- if (replacement != null) {
- replacement.augment();
- for (N parent = replacement.parent; parent != null; parent = parent.parent) {
- if (!parent.augment()) {
- break;
- }
- }
- }
-
- // Clear any previously existing links, so that we're more likely to encounter an exception if we attempt to
- // access the removed node
- parent = null;
- left = null;
- right = null;
- isRed = true;
- }
-
- /**
- * Removes this node from the tree that contains it. The effect of this method on the fields of this node is
- * unspecified. This method assumes that this is not a leaf node.
- *
- * If the node has two children, we begin by moving the node's successor to its former position, by changing the
- * successor's "left", "right", "parent", and isRed fields.
- *
- * @return The root of the resulting tree.
- */
- public N remove() {
- if (isLeaf()) {
- throw new IllegalArgumentException("Attempted to remove a leaf node");
- }
-
- // Find an arbitrary non-leaf node in the tree other than this node
- N node;
- if (parent != null) {
- node = parent;
- } else if (!left.isLeaf()) {
- node = left;
- } else if (!right.isLeaf()) {
- node = right;
- } else {
- return left;
- }
-
- removeWithoutGettingRoot();
- return node.root();
- }
-
- /**
- * Returns the root of a perfectly height-balanced subtree containing the next "size" (non-leaf) nodes from
- * "iterator", in iteration order. This method is responsible for setting the "left", "right", "parent", and isRed
- * fields of the nodes, and calling augment() as appropriate. It ignores the initial values of the "left", "right",
- * "parent", and isRed fields.
- *
- * @param iterator The nodes.
- * @param size The number of nodes.
- * @param height The "height" of the subtree's root node above the deepest leaf in the tree that contains it. Since
- * insertion fixup is slow if there are too many red nodes and deleteion fixup is slow if there are too few red
- * nodes, we compromise and have red nodes at every fourth level. We color a node red iff its "height" is equal
- * to 1 mod 4.
- * @param leaf The leaf node.
- * @return The root of the subtree.
- */
- private static > N createTree(
- Iterator extends N> iterator, int size, int height, N leaf) {
- if (size == 0) {
- return leaf;
- } else {
- N left = createTree(iterator, (size - 1) / 2, height - 1, leaf);
- N node = iterator.next();
- N right = createTree(iterator, size / 2, height - 1, leaf);
-
- node.isRed = height % 4 == 1;
- node.left = left;
- node.right = right;
- if (!left.isLeaf()) {
- left.parent = node;
- }
- if (!right.isLeaf()) {
- right.parent = node;
- }
-
- node.augment();
- return node;
- }
- }
-
- /**
- * Returns the root of a perfectly height-balanced tree containing the specified nodes, in iteration order. This
- * method is responsible for setting the "left", "right", "parent", and isRed fields of the nodes (excluding
- * "leaf"), and calling augment() as appropriate. It ignores the initial values of the "left", "right", "parent",
- * and isRed fields.
- *
- * @param nodes The nodes.
- * @param leaf The leaf node.
- * @return The root of the tree.
- */
- public static > N createTree(Collection extends N> nodes, N leaf) {
- int size = nodes.size();
- if (size == 0) {
- return leaf;
- }
-
- int height = 0;
- for (int subtreeSize = size; subtreeSize > 0; subtreeSize /= 2) {
- height++;
- }
-
- N node = createTree(nodes.iterator(), size, height, leaf);
- node.parent = null;
- node.isRed = false;
- return node;
- }
-
- /**
- * Concatenates to the end of the tree rooted at this node. To be precise, given that all of the nodes in this
- * precede the node "pivot", which precedes all of the nodes in "last", this returns the root of a tree containing
- * all of these nodes. This method destroys the trees rooted at "this" and "last". We treat "pivot" as a solitary
- * node that does not belong to any tree, and we ignore its initial "parent", "left", "right", and isRed fields.
- * This method assumes that this node and "last" are the roots of their respective trees.
- *
- * This method takes O(log N) time. It is more efficient than inserting "pivot" and then calling concatenate(last).
- * It is considerably more efficient than inserting "pivot" and all of the nodes in "last".
- */
- public N concatenate(N last, N pivot) {
- // If the black height of "first", where first = this, is less than or equal to that of "last", starting at the
- // root of "last", we keep going left until we reach a black node whose black height is equal to that of
- // "first". Then, we make "pivot" the parent of that node and of "first", coloring it red, and perform
- // insertion fixup on the pivot. If the black height of "first" is greater than that of "last", we do the
- // mirror image of the above.
-
- if (parent != null) {
- throw new IllegalArgumentException("This is not the root of a tree");
- }
- if (last.parent != null) {
- throw new IllegalArgumentException("\"last\" is not the root of a tree");
- }
-
- // Compute the black height of the trees
- int firstBlackHeight = 0;
- @SuppressWarnings("unchecked")
- N first = (N) this;
- for (N node = first; node != null; node = node.right) {
- if (!node.isRed) {
- firstBlackHeight++;
- }
- }
- int lastBlackHeight = 0;
- for (N node = last; node != null; node = node.right) {
- if (!node.isRed) {
- lastBlackHeight++;
- }
- }
-
- // Identify the children and parent of pivot
- N firstChild = first;
- N lastChild = last;
- N parent;
- if (firstBlackHeight <= lastBlackHeight) {
- parent = null;
- int blackHeight = lastBlackHeight;
- while (blackHeight > firstBlackHeight) {
- if (!lastChild.isRed) {
- blackHeight--;
- }
- parent = lastChild;
- lastChild = lastChild.left;
- }
- if (lastChild.isRed) {
- parent = lastChild;
- lastChild = lastChild.left;
- }
- } else {
- parent = null;
- int blackHeight = firstBlackHeight;
- while (blackHeight > lastBlackHeight) {
- if (!firstChild.isRed) {
- blackHeight--;
- }
- parent = firstChild;
- firstChild = firstChild.right;
- }
- if (firstChild.isRed) {
- parent = firstChild;
- firstChild = firstChild.right;
- }
- }
-
- // Add "pivot" to the tree
- pivot.isRed = true;
- pivot.parent = parent;
- if (parent != null) {
- if (firstBlackHeight < lastBlackHeight) {
- parent.left = pivot;
- } else {
- parent.right = pivot;
- }
- }
- pivot.left = firstChild;
- if (!firstChild.isLeaf()) {
- firstChild.parent = pivot;
- }
- pivot.right = lastChild;
- if (!lastChild.isLeaf()) {
- lastChild.parent = pivot;
- }
-
- // Perform insertion fixup
- return pivot.fixInsertion();
- }
-
- /**
- * Concatenates the tree rooted at "last" to the end of the tree rooted at this node. To be precise, given that all
- * of the nodes in this precede all of the nodes in "last", this returns the root of a tree containing all of these
- * nodes. This method destroys the trees rooted at "this" and "last". It assumes that this node and "last" are the
- * roots of their respective trees. This method takes O(log N) time. It is considerably more efficient than
- * inserting all of the nodes in "last".
- */
- public N concatenate(N last) {
- if (parent != null || last.parent != null) {
- throw new IllegalArgumentException("The node is not the root of a tree");
- }
- if (isLeaf()) {
- return last;
- } else if (last.isLeaf()) {
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- return nThis;
- } else {
- N node = last.min();
- last = node.remove();
- return concatenate(last, node);
- }
- }
-
- /**
- * Splits the tree rooted at this node into two trees, so that the first element of the return value is the root of
- * a tree consisting of the nodes that were before the specified node, and the second element of the return value is
- * the root of a tree consisting of the nodes that were equal to or after the specified node. This method is
- * destructive, meaning it does not preserve the original tree. It assumes that this node is the root and is in the
- * same tree as splitNode. It takes O(log N) time. It is considerably more efficient than removing all of the
- * nodes at or after splitNode and then creating a new tree from those nodes.
- *
- * @param The node at which to split the tree.
- * @return An array consisting of the resulting trees.
- */
- public N[] split(N splitNode) {
- // To split the tree, we accumulate a pre-split tree and a post-split tree. We walk down the tree toward the
- // position where we are splitting. Whenever we go left, we concatenate the right subtree with the post-split
- // tree, and whenever we go right, we concatenate the pre-split tree with the left subtree. We use the
- // concatenation algorithm described in concatenate(Object, Object). For the pivot, we use the last node where
- // we went left in the case of a left move, and the last node where we went right in the case of a right move.
- //
- // The method uses the following variables:
- //
- // node: The current node in our walk down the tree.
- // first: A node on the right spine of the pre-split tree. At the beginning of each iteration, it is the black
- // node with the same black height as "node". If the pre-split tree is empty, this is null instead.
- // firstParent: The parent of "first". If the pre-split tree is empty, this is null. Otherwise, this is the
- // same as first.parent, unless first.isLeaf().
- // firstPivot: The node where we last went right, i.e. the next node to use as a pivot when concatenating with
- // the pre-split tree.
- // advanceFirst: Whether to set "first" to be its next black descendant at the end of the loop.
- // last, lastParent, lastPivot, advanceLast: Analogous to "first", firstParent, firstPivot, and advanceFirst,
- // but for the post-split tree.
- if (parent != null) {
- throw new IllegalArgumentException("This is not the root of a tree");
- }
- if (isLeaf() || splitNode.isLeaf()) {
- throw new IllegalArgumentException("The root or the split node is a leaf");
- }
-
- // Create an array containing the path from the root to splitNode
- int depth = 1;
- N parent;
- for (parent = splitNode; parent.parent != null; parent = parent.parent) {
- depth++;
- }
- if (parent != this) {
- throw new IllegalArgumentException("The split node does not belong to this tree");
- }
- RedBlackNode>[] path = new RedBlackNode>[depth];
- for (parent = splitNode; parent != null; parent = parent.parent) {
- depth--;
- path[depth] = parent;
- }
-
- @SuppressWarnings("unchecked")
- N node = (N) this;
- N first = null;
- N firstParent = null;
- N last = null;
- N lastParent = null;
- N firstPivot = null;
- N lastPivot = null;
- while (!node.isLeaf()) {
- boolean advanceFirst = !node.isRed && firstPivot != null;
- boolean advanceLast = !node.isRed && lastPivot != null;
- if ((depth + 1 < path.length && path[depth + 1] == node.left) || depth + 1 == path.length) {
- // Left move
- if (lastPivot == null) {
- // The post-split tree is empty
- last = node.right;
- last.parent = null;
- if (last.isRed) {
- last.isRed = false;
- lastParent = last;
- last = last.left;
- }
- } else {
- // Concatenate node.right and the post-split tree
- if (node.right.isRed) {
- node.right.isRed = false;
- } else if (!node.isRed) {
- lastParent = last;
- last = last.left;
- if (last.isRed) {
- lastParent = last;
- last = last.left;
- }
- advanceLast = false;
- }
- lastPivot.isRed = true;
- lastPivot.parent = lastParent;
- if (lastParent != null) {
- lastParent.left = lastPivot;
- }
- lastPivot.left = node.right;
- if (!lastPivot.left.isLeaf()) {
- lastPivot.left.parent = lastPivot;
- }
- lastPivot.right = last;
- if (!last.isLeaf()) {
- last.parent = lastPivot;
- }
- last = lastPivot.left;
- lastParent = lastPivot;
- lastPivot.fixInsertionWithoutGettingRoot(false);
- }
- lastPivot = node;
- node = node.left;
- } else {
- // Right move
- if (firstPivot == null) {
- // The pre-split tree is empty
- first = node.left;
- first.parent = null;
- if (first.isRed) {
- first.isRed = false;
- firstParent = first;
- first = first.right;
- }
- } else {
- // Concatenate the post-split tree and node.left
- if (node.left.isRed) {
- node.left.isRed = false;
- } else if (!node.isRed) {
- firstParent = first;
- first = first.right;
- if (first.isRed) {
- firstParent = first;
- first = first.right;
- }
- advanceFirst = false;
- }
- firstPivot.isRed = true;
- firstPivot.parent = firstParent;
- if (firstParent != null) {
- firstParent.right = firstPivot;
- }
- firstPivot.right = node.left;
- if (!firstPivot.right.isLeaf()) {
- firstPivot.right.parent = firstPivot;
- }
- firstPivot.left = first;
- if (!first.isLeaf()) {
- first.parent = firstPivot;
- }
- first = firstPivot.right;
- firstParent = firstPivot;
- firstPivot.fixInsertionWithoutGettingRoot(false);
- }
- firstPivot = node;
- node = node.right;
- }
-
- depth++;
-
- // Update "first" and "last" to be the nodes at the proper black height
- if (advanceFirst) {
- firstParent = first;
- first = first.right;
- if (first.isRed) {
- firstParent = first;
- first = first.right;
- }
- }
- if (advanceLast) {
- lastParent = last;
- last = last.left;
- if (last.isRed) {
- lastParent = last;
- last = last.left;
- }
- }
- }
-
- // Add firstPivot to the pre-split tree
- N leaf = node;
- if (first == null) {
- first = leaf;
- } else {
- firstPivot.isRed = true;
- firstPivot.parent = firstParent;
- if (firstParent != null) {
- firstParent.right = firstPivot;
- }
- firstPivot.left = leaf;
- firstPivot.right = leaf;
- firstPivot.fixInsertionWithoutGettingRoot(false);
- for (first = firstPivot; first.parent != null; first = first.parent) {
- first.augment();
- }
- first.augment();
- }
-
- // Add lastPivot to the post-split tree
- lastPivot.isRed = true;
- lastPivot.parent = lastParent;
- if (lastParent != null) {
- lastParent.left = lastPivot;
- }
- lastPivot.left = leaf;
- lastPivot.right = leaf;
- lastPivot.fixInsertionWithoutGettingRoot(false);
- for (last = lastPivot; last.parent != null; last = last.parent) {
- last.augment();
- }
- last.augment();
-
- @SuppressWarnings("unchecked")
- N[] result = (N[]) Array.newInstance(getClass(), 2);
- result[0] = first;
- result[1] = last;
- return result;
- }
-
- /**
- * Returns the lowest common ancestor of this node and "other" - the node that is an ancestor of both and is not the
- * parent of a node that is an ancestor of both. Assumes that this is in the same tree as "other". Assumes that
- * neither "this" nor "other" is a leaf node. This method may return "this" or "other".
- *
- * Note that while it is possible to compute the lowest common ancestor in O(P) time, where P is the length of the
- * path from this node to "other", the "lca" method is not guaranteed to take O(P) time. If your application
- * requires this, then you should write your own lowest common ancestor method.
- */
- public N lca(N other) {
- if (isLeaf() || other.isLeaf()) {
- throw new IllegalArgumentException("One of the nodes is a leaf node");
- }
-
- // Compute the depth of each node
- int depth = 0;
- for (N parent = this.parent; parent != null; parent = parent.parent) {
- depth++;
- }
- int otherDepth = 0;
- for (N parent = other.parent; parent != null; parent = parent.parent) {
- otherDepth++;
- }
-
- // Go up to nodes of the same depth
- @SuppressWarnings("unchecked")
- N parent = (N) this;
- N otherParent = other;
- if (depth <= otherDepth) {
- for (int i = otherDepth; i > depth; i--) {
- otherParent = otherParent.parent;
- }
- } else {
- for (int i = depth; i > otherDepth; i--) {
- parent = parent.parent;
- }
- }
-
- // Find the LCA
- while (parent != otherParent) {
- parent = parent.parent;
- otherParent = otherParent.parent;
- }
- if (parent != null) {
- return parent;
- } else {
- throw new IllegalArgumentException("The nodes do not belong to the same tree");
- }
- }
-
- /**
- * Returns an integer comparing the position of this node in the tree that contains it with that of "other". Returns
- * a negative number if this is earlier, a positive number if this is later, and 0 if this is at the same position.
- * Assumes that this is in the same tree as "other". Assumes that neither "this" nor "other" is a leaf node.
- *
- * The base class's implementation takes O(log N) time. If a RedBlackNode subclass stores a value used to order the
- * nodes, then it could override compareTo to compare the nodes' values, which would take O(1) time.
- *
- * Note that while it is possible to compare the positions of two nodes in O(P) time, where P is the length of the
- * path from this node to "other", the default implementation of compareTo is not guaranteed to take O(P) time. If
- * your application requires this, then you should write your own comparison method.
- */
- @Override
- public int compareTo(N other) {
- if (isLeaf() || other.isLeaf()) {
- throw new IllegalArgumentException("One of the nodes is a leaf node");
- }
-
- // The algorithm operates as follows: compare the depth of this node to that of "other". If the depth of
- // "other" is greater, keep moving up from "other" until we find the ancestor at the same depth. Then, keep
- // moving up from "this" and from that node until we reach the lowest common ancestor. The node that arrived
- // from the left child of the common ancestor is earlier. The algorithm is analogous if the depth of "other" is
- // not greater.
- if (this == other) {
- return 0;
- }
-
- // Compute the depth of each node
- int depth = 0;
- RedBlackNode parent;
- for (parent = this; parent.parent != null; parent = parent.parent) {
- depth++;
- }
- int otherDepth = 0;
- N otherParent;
- for (otherParent = other; otherParent.parent != null; otherParent = otherParent.parent) {
- otherDepth++;
- }
-
- // Go up to nodes of the same depth
- if (depth < otherDepth) {
- otherParent = other;
- for (int i = otherDepth - 1; i > depth; i--) {
- otherParent = otherParent.parent;
- }
- if (otherParent.parent != this) {
- otherParent = otherParent.parent;
- } else if (left == otherParent) {
- return 1;
- } else {
- return -1;
- }
- parent = this;
- } else if (depth > otherDepth) {
- parent = this;
- for (int i = depth - 1; i > otherDepth; i--) {
- parent = parent.parent;
- }
- if (parent.parent != other) {
- parent = parent.parent;
- } else if (other.left == parent) {
- return -1;
- } else {
- return 1;
- }
- otherParent = other;
- } else {
- parent = this;
- otherParent = other;
- }
-
- // Keep going up until we reach the lowest common ancestor
- while (parent.parent != otherParent.parent) {
- parent = parent.parent;
- otherParent = otherParent.parent;
- }
- if (parent.parent == null) {
- throw new IllegalArgumentException("The nodes do not belong to the same tree");
- }
- if (parent.parent.left == parent) {
- return -1;
- } else {
- return 1;
- }
- }
-
- /**
- * Throws a RuntimeException if the RedBlackNode fields of this are not correct for a leaf node.
- */
- private void assertIsValidLeaf() {
- if (left != null || right != null || parent != null || isRed) {
- throw new RuntimeException("A leaf node's \"left\", \"right\", \"parent\", or isRed field is incorrect");
- }
- }
-
- /**
- * Throws a RuntimeException if the subtree rooted at this node does not satisfy the red-black properties, excluding
- * the requirement that the root be black, or it contains a repeated node other than a leaf node.
- *
- * @param blackHeight The required number of black nodes in each path from this to a leaf node, including this and
- * the leaf node.
- * @param visited The nodes we have reached thus far, other than leaf nodes. This method adds the non-leaf nodes in
- * the subtree rooted at this node to "visited".
- */
- private void assertSubtreeIsValidRedBlack(int blackHeight, Set> visited) {
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- if (left == null || right == null) {
- assertIsValidLeaf();
- if (blackHeight != 1) {
- throw new RuntimeException("Not all root-to-leaf paths have the same number of black nodes");
- }
- return;
- } else if (!visited.add(new Reference(nThis))) {
- throw new RuntimeException("The tree contains a repeated non-leaf node");
- } else {
- int childBlackHeight;
- if (isRed) {
- if ((!left.isLeaf() && left.isRed) || (!right.isLeaf() && right.isRed)) {
- throw new RuntimeException("A red node has a red child");
- }
- childBlackHeight = blackHeight;
- } else if (blackHeight == 0) {
- throw new RuntimeException("Not all root-to-leaf paths have the same number of black nodes");
- } else {
- childBlackHeight = blackHeight - 1;
- }
-
- if (!left.isLeaf() && left.parent != this) {
- throw new RuntimeException("left.parent != this");
- }
- if (!right.isLeaf() && right.parent != this) {
- throw new RuntimeException("right.parent != this");
- }
- RedBlackNode leftNode = left;
- RedBlackNode rightNode = right;
- leftNode.assertSubtreeIsValidRedBlack(childBlackHeight, visited);
- rightNode.assertSubtreeIsValidRedBlack(childBlackHeight, visited);
- }
- }
-
- /**
- * Calls assertNodeIsValid() on every node in the subtree rooted at this node.
- */
- private void assertNodesAreValid() {
- assertNodeIsValid();
- if (left != null) {
- RedBlackNode leftNode = left;
- RedBlackNode rightNode = right;
- leftNode.assertNodesAreValid();
- rightNode.assertNodesAreValid();
- }
- }
-
- /**
- * Throws a RuntimeException if the subtree rooted at this node is not a valid red-black tree, e.g. if a red node
- * has a red child or it contains a non-leaf node "node" for which node.left.parent != node. (If parent != null,
- * it's okay if isRed is true.) This method is useful for debugging. See also assertSubtreeIsValid().
- */
- public void assertSubtreeIsValidRedBlack() {
- if (isLeaf()) {
- assertIsValidLeaf();
- } else {
- if (parent == null && isRed) {
- throw new RuntimeException("The root is red");
- }
-
- // Compute the black height of the tree
- Set> nodes = new HashSet>();
- int blackHeight = 0;
- @SuppressWarnings("unchecked")
- N node = (N) this;
- while (node != null) {
- if (!nodes.add(new Reference(node))) {
- throw new RuntimeException("The tree contains a repeated non-leaf node");
- }
- if (!node.isRed) {
- blackHeight++;
- }
- node = node.left;
- }
-
- assertSubtreeIsValidRedBlack(blackHeight, new HashSet>());
- }
- }
-
- /**
- * Throws a RuntimeException if we detect a problem with the subtree rooted at this node, such as a red child of a
- * red node or a non-leaf descendant "node" for which node.left.parent != node. This method is useful for
- * debugging. RedBlackNode subclasses may want to override assertSubtreeIsValid() to call assertOrderIsValid.
- */
- public void assertSubtreeIsValid() {
- assertSubtreeIsValidRedBlack();
- assertNodesAreValid();
- }
-
- /**
- * Throws a RuntimeException if the nodes in the subtree rooted at this node are not in the specified order or they
- * do not lie in the specified range. Assumes that the subtree rooted at this node is a valid binary tree, i.e. it
- * has no repeated nodes other than leaf nodes.
- *
- * @param comparator A comparator indicating how the nodes should be ordered.
- * @param start The lower limit for nodes in the subtree, if any.
- * @param end The upper limit for nodes in the subtree, if any.
- */
- private void assertOrderIsValid(Comparator super N> comparator, N start, N end) {
- if (!isLeaf()) {
- @SuppressWarnings("unchecked")
- N nThis = (N) this;
- if (start != null && comparator.compare(nThis, start) < 0) {
- throw new RuntimeException("The nodes are not ordered correctly");
- }
- if (end != null && comparator.compare(nThis, end) > 0) {
- throw new RuntimeException("The nodes are not ordered correctly");
- }
- RedBlackNode leftNode = left;
- RedBlackNode rightNode = right;
- leftNode.assertOrderIsValid(comparator, start, nThis);
- rightNode.assertOrderIsValid(comparator, nThis, end);
- }
- }
-
- /**
- * Throws a RuntimeException if the nodes in the subtree rooted at this node are not in the specified order.
- * Assumes that this is a valid binary tree, i.e. there are no repeated nodes other than leaf nodes. This method is
- * useful for debugging. RedBlackNode subclasses may want to override assertSubtreeIsValid() to call
- * assertOrderIsValid.
- *
- * @param comparator A comparator indicating how the nodes should be ordered. If this is null, we use the nodes'
- * natural order, as in N.compareTo.
- */
- public void assertOrderIsValid(Comparator super N> comparator) {
- if (comparator == null) {
- comparator = naturalOrder();
- }
- assertOrderIsValid(comparator, null, null);
- }
-}
-
diff --git a/src/main/java/baritone/builder/utils/com/github/btrekkie/red_black_node/Reference.java b/src/main/java/baritone/builder/utils/com/github/btrekkie/red_black_node/Reference.java
deleted file mode 100644
index 5c079f743..000000000
--- a/src/main/java/baritone/builder/utils/com/github/btrekkie/red_black_node/Reference.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * This file was originally written by btrekkie under the MIT license, which is compatible with the LGPL license for this usage within Baritone
- * https://github.com/btrekkie/RedBlackNode/blob/master/src/main/java/com/github/btrekkie/red_black_node/Reference.java
- */
-
-package baritone.builder.utils.com.github.btrekkie.red_black_node;
-
-/**
- * Wraps a value using reference equality. In other words, two references are equal only if their values are the same
- * object instance, as in ==.
- *
- * @param The type of value.
- */
-class Reference {
- /**
- * The value this wraps.
- */
- private final T value;
-
- public Reference(T value) {
- this.value = value;
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof Reference)) {
- return false;
- }
- Reference> reference = (Reference>) obj;
- return value == reference.value;
- }
-
- @Override
- public int hashCode() {
- return System.identityHashCode(value);
- }
-}
-
diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java
deleted file mode 100644
index 90374ca52..000000000
--- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderCollection.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.github.btrekkie.arbitrary_order_collection;
-
-import java.util.Comparator;
-
-/**
- * Provides objects ordered in an arbitrary, but consistent fashion, through the createValue() method. To determine the
- * relative order of two values, use ArbitraryOrderValue.compareTo. We may only compare values on which we have not
- * called "remove" that were created in the same ArbitraryOrderCollection instance. Note that despite the name,
- * ArbitraryOrderCollection does not implement Collection.
- */
-/* We implement an ArbitraryOrderCollection using a red-black tree. We order the nodes arbitrarily.
- */
-public class ArbitraryOrderCollection {
- /**
- * The Comparator for ordering ArbitraryOrderNodes.
- */
- private static final Comparator NODE_COMPARATOR = new Comparator() {
- @Override
- public int compare(ArbitraryOrderNode node1, ArbitraryOrderNode node2) {
- return 0;
- }
- };
-
- /**
- * The root node of the tree.
- */
- private ArbitraryOrderNode root = new ArbitraryOrderNode();
-
- /**
- * Adds and returns a new value for ordering.
- */
- public ArbitraryOrderValue createValue() {
- ArbitraryOrderNode node = new ArbitraryOrderNode();
- root = root.insert(node, true, NODE_COMPARATOR);
- return new ArbitraryOrderValue(node);
- }
-
- /**
- * Removes the specified value from this collection. Assumes we obtained the value by calling createValue() on this
- * instance of ArbitraryOrderCollection. After calling "remove" on a value, we may no longer compare it to other
- * values.
- */
- public void remove(ArbitraryOrderValue value) {
- root = value.node.remove();
- }
-}
diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java
deleted file mode 100644
index 517ddfcee..000000000
--- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderNode.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.github.btrekkie.arbitrary_order_collection;
-
-import baritone.builder.utils.com.github.btrekkie.red_black_node.RedBlackNode;
-
-/**
- * A node in an ArbitraryOrderCollection tree. See ArbitraryOrderCollection.
- */
-class ArbitraryOrderNode extends RedBlackNode {
-
-}
diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java
deleted file mode 100644
index 160c4ee75..000000000
--- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/ArbitraryOrderValue.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.github.btrekkie.arbitrary_order_collection;
-
-/**
- * A value in an ArbitraryOrderCollection. To determine the relative order of two values in the same collection, call
- * compareTo.
- */
-public class ArbitraryOrderValue implements Comparable {
- /**
- * The node that establishes this value's relative position.
- */
- final ArbitraryOrderNode node;
-
- ArbitraryOrderValue(ArbitraryOrderNode node) {
- this.node = node;
- }
-
- @Override
- public int compareTo(ArbitraryOrderValue other) {
- return node.compareTo(other.node);
- }
-}
diff --git a/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java b/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java
deleted file mode 100644
index ad36a5c62..000000000
--- a/src/test/java/com/github/btrekkie/arbitrary_order_collection/test/ArbitraryOrderCollectionTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.github.btrekkie.arbitrary_order_collection.test;
-
-import com.github.btrekkie.arbitrary_order_collection.ArbitraryOrderCollection;
-import com.github.btrekkie.arbitrary_order_collection.ArbitraryOrderValue;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class ArbitraryOrderCollectionTest {
- /**
- * Tests ArbitraryOrderCollection.
- */
- @Test
- public void test() {
- ArbitraryOrderCollection collection = new ArbitraryOrderCollection();
- List values1 = new ArrayList(5);
- ArbitraryOrderValue value = collection.createValue();
- assertEquals(0, value.compareTo(value));
- values1.add(value);
- for (int i = 0; i < 4; i++) {
- values1.add(collection.createValue());
- }
- Collections.sort(values1);
- List values2 = new ArrayList(10);
- for (int i = 0; i < 10; i++) {
- value = collection.createValue();
- values2.add(value);
- }
- for (int i = 0; i < 5; i++) {
- collection.remove(values2.get(2 * i));
- }
- assertEquals(0, values1.get(0).compareTo(values1.get(0)));
- assertTrue(values1.get(0).compareTo(values1.get(1)) < 0);
- assertTrue(values1.get(1).compareTo(values1.get(0)) > 0);
- assertTrue(values1.get(4).compareTo(values1.get(2)) > 0);
- assertTrue(values1.get(0).compareTo(values1.get(4)) < 0);
-
- collection = new ArbitraryOrderCollection();
- values1 = new ArrayList(1000);
- for (int i = 0; i < 1000; i++) {
- value = collection.createValue();
- values1.add(value);
- }
- for (int i = 0; i < 500; i++) {
- collection.remove(values1.get(2 * i));
- }
- values2 = new ArrayList(500);
- for (int i = 0; i < 500; i++) {
- values2.add(values1.get(2 * i + 1));
- }
- for (int i = 0; i < 500; i++) {
- values2.get(0).compareTo(values2.get(i));
- }
- Collections.sort(values2);
- for (int i = 0; i < 500; i++) {
- collection.createValue();
- }
- for (int i = 0; i < 499; i++) {
- assertTrue(values2.get(i).compareTo(values2.get(i + 1)) < 0);
- assertTrue(values2.get(i + 1).compareTo(values2.get(i)) > 0);
- }
- for (int i = 1; i < 500; i++) {
- assertEquals(0, values2.get(i).compareTo(values2.get(i)));
- assertTrue(values2.get(0).compareTo(values2.get(i)) < 0);
- assertTrue(values2.get(i).compareTo(values2.get(0)) > 0);
- }
- }
-}
diff --git a/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java b/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java
deleted file mode 100644
index aa0204517..000000000
--- a/src/test/java/com/github/btrekkie/interval_tree/IntervalTree.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.github.btrekkie.interval_tree;
-
-/**
- * An interval tree data structure, which supports adding or removing an interval and finding an arbitrary interval that
- * contains a specified value.
- */
-/* The interval tree is ordered in ascending order of the start an interval, with ties broken by the end of the
- * interval. Each node is augmented with the maximum ending value of an interval in the subtree rooted at the node.
- */
-public class IntervalTree {
- /**
- * The root node of the tree.
- */
- private IntervalTreeNode root = IntervalTreeNode.LEAF;
-
- /**
- * Adds the specified interval to this.
- */
- public void addInterval(IntervalTreeInterval interval) {
- root = root.insert(new IntervalTreeNode(interval), true, null);
- }
-
- /**
- * Removes the specified interval from this, if it is present.
- *
- * @param interval The interval.
- * @return Whether the interval was present.
- */
- public boolean removeInterval(IntervalTreeInterval interval) {
- IntervalTreeNode node = root;
- while (!node.isLeaf()) {
- if (interval.start < node.interval.start) {
- node = node.left;
- } else if (interval.start > node.interval.start) {
- node = node.right;
- } else if (interval.end < node.interval.end) {
- node = node.left;
- } else if (interval.end > node.interval.end) {
- node = node.right;
- } else {
- root = node.remove();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns an aribtrary IntervalTreeInterval in this that contains the specified value. Returns null if there is no
- * such interval.
- */
- public IntervalTreeInterval findInterval(double value) {
- IntervalTreeNode node = root;
- while (!node.isLeaf()) {
- if (value >= node.interval.start && value <= node.interval.end) {
- return node.interval;
- } else if (value <= node.left.maxEnd) {
- node = node.left;
- } else {
- node = node.right;
- }
- }
- return null;
- }
-}
diff --git a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java b/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java
deleted file mode 100644
index 182eb37c6..000000000
--- a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeInterval.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.github.btrekkie.interval_tree;
-
-/**
- * An inclusive range of values [start, end]. Two intervals are equal if they have the same starting and ending values.
- */
-public class IntervalTreeInterval {
- /**
- * The smallest value in the range.
- */
- public final double start;
-
- /**
- * The largest value in the range.
- */
- public final double end;
-
- public IntervalTreeInterval(double start, double end) {
- if (start > end) {
- throw new IllegalArgumentException("The end of the range must be at most the start");
- }
- this.start = start;
- this.end = end;
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof IntervalTreeInterval)) {
- return false;
- }
- IntervalTreeInterval interval = (IntervalTreeInterval) obj;
- return start == interval.start && end == interval.end;
- }
-}
diff --git a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java b/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java
deleted file mode 100644
index c39417e7e..000000000
--- a/src/test/java/com/github/btrekkie/interval_tree/IntervalTreeNode.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.github.btrekkie.interval_tree;
-
-import baritone.builder.utils.com.github.btrekkie.red_black_node.RedBlackNode;
-
-/**
- * A node in an IntervalTree. See the comments for the implementation of IntervalTree. Its compareTo method orders
- * nodes as suggested in the comments for the implementation of IntervalTree.
- */
-class IntervalTreeNode extends RedBlackNode {
- /**
- * The dummy leaf node.
- */
- public static final IntervalTreeNode LEAF = new IntervalTreeNode();
-
- /**
- * The interval stored in this node.
- */
- public IntervalTreeInterval interval;
-
- /**
- * The maximum ending value of an interval in the subtree rooted at this node.
- */
- public double maxEnd;
-
- public IntervalTreeNode(IntervalTreeInterval interval) {
- this.interval = interval;
- maxEnd = interval.end;
- }
-
- /**
- * Constructs a new dummy leaf node.
- */
- private IntervalTreeNode() {
- interval = null;
- maxEnd = Double.NEGATIVE_INFINITY;
- }
-
- @Override
- public boolean augment() {
- double newMaxEnd = Math.max(interval.end, Math.max(left.maxEnd, right.maxEnd));
- if (newMaxEnd == maxEnd) {
- return false;
- } else {
- maxEnd = newMaxEnd;
- return true;
- }
- }
-
- @Override
- public void assertNodeIsValid() {
- double expectedMaxEnd;
- if (isLeaf()) {
- expectedMaxEnd = Double.NEGATIVE_INFINITY;
- } else {
- expectedMaxEnd = Math.max(interval.end, Math.max(left.maxEnd, right.maxEnd));
- }
- if (maxEnd != expectedMaxEnd) {
- throw new RuntimeException("The node's maxEnd does not match that of the children");
- }
- }
-
- @Override
- public int compareTo(IntervalTreeNode other) {
- if (interval.start != interval.end) {
- return Double.compare(interval.start, other.interval.start);
- } else {
- return Double.compare(interval.end, other.interval.end);
- }
- }
-
- @Override
- public void assertSubtreeIsValid() {
- super.assertSubtreeIsValid();
- assertOrderIsValid(null);
- }
-}
diff --git a/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java b/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java
deleted file mode 100644
index 5af2bd6d2..000000000
--- a/src/test/java/com/github/btrekkie/interval_tree/test/IntervalTreeTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.github.btrekkie.interval_tree.test;
-
-import com.github.btrekkie.interval_tree.IntervalTree;
-import com.github.btrekkie.interval_tree.IntervalTreeInterval;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class IntervalTreeTest {
- /**
- * Tests IntervalTree.
- */
- @Test
- public void test() {
- IntervalTree tree = new IntervalTree();
- assertNull(tree.findInterval(0.5));
- assertNull(tree.findInterval(-1));
- tree.addInterval(new IntervalTreeInterval(5, 7));
- tree.addInterval(new IntervalTreeInterval(42, 48));
- tree.addInterval(new IntervalTreeInterval(-1, 2));
- tree.addInterval(new IntervalTreeInterval(6, 12));
- tree.addInterval(new IntervalTreeInterval(21, 23));
- assertTrue(tree.removeInterval(new IntervalTreeInterval(-1, 2)));
- assertFalse(tree.removeInterval(new IntervalTreeInterval(-1, 2)));
- tree.addInterval(new IntervalTreeInterval(-6, -2));
- assertEquals(new IntervalTreeInterval(6, 12), tree.findInterval(8));
- assertNull(tree.findInterval(0));
- assertEquals(new IntervalTreeInterval(21, 23), tree.findInterval(21));
- assertEquals(new IntervalTreeInterval(42, 48), tree.findInterval(48));
- IntervalTreeInterval interval = tree.findInterval(6.5);
- assertTrue(new IntervalTreeInterval(5, 7).equals(interval) || new IntervalTreeInterval(6, 12).equals(interval));
-
- tree = new IntervalTree();
- for (int i = 0; i < 500; i++) {
- tree.addInterval(new IntervalTreeInterval(2 * i, 2 * i + 1));
- }
- for (int i = 0; i < 250; i++) {
- tree.removeInterval(new IntervalTreeInterval(4 * i + 2, 4 * i + 3));
- }
- assertNull(tree.findInterval(123.5));
- assertEquals(new IntervalTreeInterval(124, 125), tree.findInterval(124.5));
- assertEquals(new IntervalTreeInterval(776, 777), tree.findInterval(776));
- assertEquals(new IntervalTreeInterval(0, 1), tree.findInterval(0.5));
- assertEquals(new IntervalTreeInterval(996, 997), tree.findInterval(997));
- }
-}
diff --git a/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java b/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java
deleted file mode 100644
index b487e54fe..000000000
--- a/src/test/java/com/github/btrekkie/red_black_node/test/RedBlackNodeTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package com.github.btrekkie.red_black_node.test;
-
-import org.junit.Test;
-
-import java.util.Comparator;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests RedBlackNode. Most of the testing for RedBlackNode takes place in TreeListTest, IntervalTreeTest,
- * SubArrayMinTest, and ArbitraryOrderCollectionTest, which test realistic use cases of RedBlackNode. TreeListTest
- * tests most of the RedBlackNode methods, while IntervalTreeTest tests the "insert" method, SubArrayMinTest tests
- * "lca", ArbitraryOrderCollectionTest tests compareTo, and RedBlackNodeTest tests assertSubtreeIsValid() and
- * assertOrderIsValid.
- */
-public class RedBlackNodeTest {
- /**
- * Returns whether the subtree rooted at the specified node is valid, as in TestRedBlackNode.assertSubtreeIsValid().
- */
- private boolean isSubtreeValid(TestRedBlackNode node) {
- try {
- node.assertSubtreeIsValid();
- return true;
- } catch (RuntimeException exception) {
- return false;
- }
- }
-
- /**
- * Returns whether the nodes in the subtree rooted at the specified node are ordered correctly, as in
- * TestRedBlackNode.assertOrderIsValid.
- *
- * @param comparator A comparator indicating how the nodes should be ordered. If this is null, we use the nodes'
- * natural ordering, as in TestRedBlackNode.compare.
- */
- private boolean isOrderValid(TestRedBlackNode node, Comparator comparator) {
- try {
- node.assertOrderIsValid(null);
- return true;
- } catch (RuntimeException exception) {
- return false;
- }
- }
-
- /**
- * Tests RedBlackNode.assertSubtreeIsValid() and RedBlackNode.assertOrderIsValid.
- */
- @Test
- public void testAssertIsValid() {
- // Create a perfectly balanced tree of height 3
- TestRedBlackNode node0 = new TestRedBlackNode(0);
- TestRedBlackNode node1 = new TestRedBlackNode(1);
- TestRedBlackNode node2 = new TestRedBlackNode(2);
- TestRedBlackNode node3 = new TestRedBlackNode(3);
- TestRedBlackNode node4 = new TestRedBlackNode(4);
- TestRedBlackNode node5 = new TestRedBlackNode(5);
- TestRedBlackNode node6 = new TestRedBlackNode(6);
- node0.parent = node1;
- node0.left = TestRedBlackNode.LEAF;
- node0.right = TestRedBlackNode.LEAF;
- node1.parent = node3;
- node1.left = node0;
- node1.right = node2;
- node1.isRed = true;
- node2.parent = node1;
- node2.left = TestRedBlackNode.LEAF;
- node2.right = TestRedBlackNode.LEAF;
- node3.left = node1;
- node3.right = node5;
- node4.parent = node5;
- node4.left = TestRedBlackNode.LEAF;
- node4.right = TestRedBlackNode.LEAF;
- node5.parent = node3;
- node5.left = node4;
- node5.right = node6;
- node5.isRed = true;
- node6.parent = node5;
- node6.left = TestRedBlackNode.LEAF;
- node6.right = TestRedBlackNode.LEAF;
-
- node3.left = node3;
- node3.right = node3;
- node3.parent = node3;
- assertFalse(isSubtreeValid(node3));
- node3.left = node1;
- node3.right = node5;
- node3.parent = null;
-
- node0.parent = node3;
- assertFalse(isSubtreeValid(node3));
- node0.parent = node1;
-
- node1.right = node0;
- assertFalse(isSubtreeValid(node3));
- node1.right = node2;
-
- node5.isRed = false;
- assertFalse(isSubtreeValid(node3));
- assertTrue(isSubtreeValid(node5));
- node5.isRed = true;
-
- node3.isRed = true;
- assertFalse(isSubtreeValid(node3));
- assertTrue(isSubtreeValid(node5));
- node3.isRed = false;
-
- node0.isRed = true;
- node2.isRed = true;
- node4.isRed = true;
- node6.isRed = true;
- assertFalse(isSubtreeValid(node3));
- node0.isRed = false;
- node2.isRed = false;
- node4.isRed = false;
- node6.isRed = false;
-
- TestRedBlackNode.LEAF.isRed = true;
- assertFalse(isSubtreeValid(node3));
- TestRedBlackNode.LEAF.isRed = false;
-
- TestRedBlackNode.LEAF.isValid = false;
- assertFalse(isSubtreeValid(node3));
- assertFalse(isSubtreeValid(TestRedBlackNode.LEAF));
- TestRedBlackNode.LEAF.isValid = true;
-
- node1.isValid = false;
- assertFalse(isSubtreeValid(node3));
- node1.isValid = true;
-
- node3.value = 2;
- node2.value = 3;
- assertFalse(isOrderValid(node3, null));
- assertFalse(
- isOrderValid(node3, new Comparator() {
- @Override
- public int compare(TestRedBlackNode node1, TestRedBlackNode node2) {
- return node1.value - node2.value;
- }
- }));
- node3.value = 3;
- node2.value = 2;
-
- node2.value = 4;
- node4.value = 2;
- assertFalse(isOrderValid(node3, null));
- node2.value = 2;
- node4.value = 4;
-
- node0.value = 1;
- node1.value = 0;
- assertFalse(isOrderValid(node3, null));
- node0.value = 0;
- node1.value = 1;
-
- // Do all of the assertions for which the tree is supposed to be valid at the end, to make sure we didn't make a
- // mistake undoing any of the modifications
- assertTrue(isSubtreeValid(node3));
- assertTrue(isSubtreeValid(node1));
- assertTrue(isSubtreeValid(node0));
- assertTrue(isSubtreeValid(TestRedBlackNode.LEAF));
- assertTrue(isOrderValid(node3, null));
- assertTrue(isOrderValid(node1, null));
- assertTrue(isOrderValid(node0, null));
- assertTrue(isOrderValid(TestRedBlackNode.LEAF, null));
- assertTrue(
- isOrderValid(node3, new Comparator() {
- @Override
- public int compare(TestRedBlackNode node1, TestRedBlackNode node2) {
- return node1.value - node2.value;
- }
- }));
- }
-}
diff --git a/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java b/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java
deleted file mode 100644
index 781f8a85b..000000000
--- a/src/test/java/com/github/btrekkie/red_black_node/test/TestRedBlackNode.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.github.btrekkie.red_black_node.test;
-
-import baritone.builder.utils.com.github.btrekkie.red_black_node.RedBlackNode;
-
-/**
- * A RedBlackNode for RedBlackNodeTest.
- */
-class TestRedBlackNode extends RedBlackNode {
- /**
- * The dummy leaf node.
- */
- public static final TestRedBlackNode LEAF = new TestRedBlackNode();
-
- /**
- * The value stored in this node. "value" is unspecified if this is a leaf node.
- */
- public int value;
-
- /**
- * Whether this node is considered valid, as in assertNodeIsValid().
- */
- public boolean isValid = true;
-
- public TestRedBlackNode(int value) {
- this.value = value;
- }
-
- /**
- * Constructs a new dummy leaf node.
- */
- private TestRedBlackNode() {
-
- }
-
- @Override
- public void assertNodeIsValid() {
- if (!isValid) {
- throw new RuntimeException("isValid is false");
- }
- }
-
- @Override
- public int compareTo(TestRedBlackNode other) {
- return value - other.value;
- }
-}
diff --git a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java b/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java
deleted file mode 100644
index 7c8e1c4ba..000000000
--- a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMin.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.github.btrekkie.sub_array_min;
-
-/**
- * A list of integers. SubArrayMin provides the ability to quickly determine the minimum value in a given sublist.
- */
-/* We implement SubArrayMin using a red-black tree augmented by subtree size and minimum value. Using the subtree size
- * augmentation, we can find the node at a given index.
- */
-public class SubArrayMin {
- /**
- * The root node.
- */
- private SubArrayMinNode root = SubArrayMinNode.LEAF;
-
- /**
- * Appends the specified value to the end of the list.
- */
- public void add(int value) {
- SubArrayMinNode newNode = new SubArrayMinNode(value);
- newNode.left = SubArrayMinNode.LEAF;
- newNode.right = SubArrayMinNode.LEAF;
- if (root.isLeaf()) {
- root = newNode;
- newNode.augment();
- } else {
- SubArrayMinNode node = root.max();
- node.right = newNode;
- newNode.parent = node;
- newNode.isRed = true;
- root = newNode.fixInsertion();
- }
- }
-
- /**
- * Returns the node for the element with the specified index. Assumes "index" is in the range [0, root.size).
- */
- private SubArrayMinNode getNode(int index) {
- if (index < 0 || index >= root.size) {
- throw new IndexOutOfBoundsException("Index " + index + " is not in the range [0, " + root.size + ")");
- }
- int rank = index;
- SubArrayMinNode node = root;
- while (rank != node.left.size) {
- if (rank < node.left.size) {
- node = node.left;
- } else {
- rank -= node.left.size + 1;
- node = node.right;
- }
- }
- return node;
- }
-
- /**
- * Returns the minimum value in the subarray starting at index startIndex and ending at index endIndex - 1,
- * inclusive. Assumes startIndex < endIndex, and assumes this contains indices startIndex and endIndex - 1.
- */
- public int min(int startIndex, int endIndex) {
- if (startIndex >= endIndex) {
- throw new IllegalArgumentException("The start index must be less than the end index");
- }
- SubArrayMinNode start = getNode(startIndex);
- SubArrayMinNode end = getNode(endIndex - 1);
- SubArrayMinNode lca = start.lca(end);
-
- int min = Math.min(lca.value, Math.min(start.value, end.value));
- if (start != lca) {
- if (start.right.min < min) {
- min = start.right.min;
- }
- for (SubArrayMinNode node = start; node.parent != lca; node = node.parent) {
- if (node.parent.left == node) {
- if (node.parent.value < min) {
- min = node.parent.value;
- }
- if (node.parent.right.min < min) {
- min = node.parent.right.min;
- }
- }
- }
- }
- if (end != lca) {
- if (end.left.min < min) {
- min = end.left.min;
- }
- for (SubArrayMinNode node = end; node.parent != lca; node = node.parent) {
- if (node.parent.right == node) {
- if (node.parent.value < min) {
- min = node.parent.value;
- }
- if (node.parent.left.min < min) {
- min = node.parent.left.min;
- }
- }
- }
- }
- return min;
- }
-}
diff --git a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java b/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java
deleted file mode 100644
index 6ff1b155a..000000000
--- a/src/test/java/com/github/btrekkie/sub_array_min/SubArrayMinNode.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.github.btrekkie.sub_array_min;
-
-import baritone.builder.utils.com.github.btrekkie.red_black_node.RedBlackNode;
-
-/**
- * A node in a SubArrayMin object. See the comments for the implementation of that class.
- */
-class SubArrayMinNode extends RedBlackNode {
- /**
- * The dummy leaf node.
- */
- public static final SubArrayMinNode LEAF = new SubArrayMinNode();
-
- /**
- * The element stored in the node. The value is unspecified if this is a leaf node.
- */
- public final int value;
-
- /**
- * The number of elements in the subtree rooted at this node.
- */
- public int size;
-
- /**
- * The minimum element in the subtree rooted at this node. This is Integer.MAX_VALUE if this is a leaf node.
- */
- public int min;
-
- public SubArrayMinNode(int value) {
- this.value = value;
- }
-
- private SubArrayMinNode() {
- value = 0;
- min = Integer.MAX_VALUE;
- }
-
- @Override
- public boolean augment() {
- int newSize = left.size + right.size + 1;
- int newMin = Math.min(value, Math.min(left.min, right.min));
- if (newSize == size && newMin == min) {
- return false;
- } else {
- size = newSize;
- min = newMin;
- return true;
- }
- }
-
- @Override
- public void assertNodeIsValid() {
- int expectedSize;
- int expectedMin;
- if (isLeaf()) {
- expectedSize = 0;
- expectedMin = Integer.MAX_VALUE;
- } else {
- expectedSize = left.size + right.size + 1;
- expectedMin = Math.min(value, Math.min(left.min, right.min));
- }
- if (size != expectedSize || min != expectedMin) {
- throw new RuntimeException("The node's size or minimum value does not match that of the children");
- }
- }
-}
diff --git a/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java b/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java
deleted file mode 100644
index 95266b387..000000000
--- a/src/test/java/com/github/btrekkie/sub_array_min/test/SubArrayMinTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.github.btrekkie.sub_array_min.test;
-
-import com.github.btrekkie.sub_array_min.SubArrayMin;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class SubArrayMinTest {
- /**
- * Tests SubArrayMin.
- */
- @Test
- public void test() {
- SubArrayMin sam = new SubArrayMin();
- sam.add(12);
- sam.add(42);
- sam.add(-3);
- sam.add(16);
- sam.add(5);
- sam.add(8);
- sam.add(4);
- assertEquals(-3, sam.min(0, 7));
- assertEquals(12, sam.min(0, 2));
- assertEquals(-3, sam.min(2, 4));
- assertEquals(12, sam.min(0, 1));
- assertEquals(5, sam.min(3, 6));
- assertEquals(4, sam.min(4, 7));
-
- sam = new SubArrayMin();
- for (int i = 0; i < 1000; i++) {
- sam.add(-Integer.bitCount(i));
- }
- assertEquals(0, sam.min(0, 1));
- assertEquals(-4, sam.min(0, 30));
- assertEquals(-9, sam.min(0, 1000));
- assertEquals(-9, sam.min(123, 777));
- assertEquals(-8, sam.min(777, 888));
- assertEquals(-6, sam.min(777, 788));
- assertEquals(-9, sam.min(900, 1000));
- }
-}