├── .classpath ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── .travis.yml ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── build.xml ├── lib └── junit-4_4.3.1.jar ├── src └── com │ └── jwetherell │ └── algorithms │ ├── data_structures │ ├── AVLTree.java │ ├── BTree.java │ ├── BinaryHeap.java │ ├── BinarySearchTree.java │ ├── CompactSuffixTrie.java │ ├── DisjointSet.java │ ├── FenwickTree.java │ ├── Graph.java │ ├── HashArrayMappedTrie.java │ ├── HashMap.java │ ├── ImplicitKeyTreap.java │ ├── IntervalSum.java │ ├── IntervalTree.java │ ├── KdTree.java │ ├── LCPArray.java │ ├── List.java │ ├── LowestCommonAncestor.java │ ├── Matrix.java │ ├── PatriciaTrie.java │ ├── QuadTree.java │ ├── Queue.java │ ├── RadixTrie.java │ ├── RedBlackTree.java │ ├── SegmentTree.java │ ├── SkipList.java │ ├── SkipListMap.java │ ├── SplayTree.java │ ├── Stack.java │ ├── SuffixArray.java │ ├── SuffixTree.java │ ├── SuffixTrie.java │ ├── TernarySearchTree.java │ ├── Treap.java │ ├── TreeMap.java │ ├── Trie.java │ ├── TrieMap.java │ └── interfaces │ │ ├── IHeap.java │ │ ├── IList.java │ │ ├── IMap.java │ │ ├── IQueue.java │ │ ├── ISet.java │ │ ├── IStack.java │ │ ├── ISuffixTree.java │ │ └── ITree.java │ ├── graph │ ├── AStar.java │ ├── BellmanFord.java │ ├── BreadthFirstTraversal.java │ ├── ConnectedComponents.java │ ├── CycleDetection.java │ ├── DepthFirstTraversal.java │ ├── Dijkstra.java │ ├── EdmondsKarp.java │ ├── FloydWarshall.java │ ├── Johnson.java │ ├── Kruskal.java │ ├── Prim.java │ ├── PushRelabel.java │ ├── TopologicalSort.java │ └── TurboMatching.java │ ├── mathematics │ ├── Coprimes.java │ ├── DiscreteLogarithm.java │ ├── Distance.java │ ├── Division.java │ ├── Exponentiation.java │ ├── FastFourierTransform.java │ ├── GreatestCommonDivisor.java │ ├── Knapsack.java │ ├── LUDecomposition.java │ ├── Modular.java │ ├── Multiplication.java │ ├── Permutations.java │ ├── Primes.java │ └── RamerDouglasPeucker.java │ ├── numbers │ ├── Complex.java │ ├── Integers.java │ └── Longs.java │ ├── search │ ├── BinarySearch.java │ ├── InterpolationSearch.java │ ├── LinearSearch.java │ ├── LowerBound.java │ ├── QuickSelect.java │ └── UpperBound.java │ ├── sequence │ ├── ArithmeticProgression.java │ ├── FibonacciSequence.java │ ├── LargestSumContiguousSubarray.java │ ├── LongestCommonSubsequence.java │ ├── LongestIncreasingSubsequence.java │ ├── LongestPalindromicSubsequence.java │ └── SubsequenceCounter.java │ ├── sorts │ ├── AmericanFlagSort.java │ ├── BubbleSort.java │ ├── CountingSort.java │ ├── HeapSort.java │ ├── InsertionSort.java │ ├── MergeSort.java │ ├── QuickSort.java │ ├── RadixSort.java │ └── ShellSort.java │ └── strings │ ├── KnuthMorrisPratt.java │ ├── Manacher.java │ ├── Rotation.java │ └── StringFunctions.java └── test └── com └── jwetherell └── algorithms ├── data_structures ├── test │ ├── AVLTreeTests.java │ ├── AllTests.java │ ├── BTreeTests.java │ ├── BinaryHeapTests.java │ ├── BinarySearchTreeTests.java │ ├── CompactSuffixTrieTests.java │ ├── DisjointSetTests.java │ ├── FenwickTreeTests.java │ ├── GraphTests.java │ ├── HashArrayMappedTreeTests.java │ ├── HashMapTests.java │ ├── ImplicitKeyTreapTests.java │ ├── IntervalSumTest.java │ ├── IntervalTreeTests.java │ ├── KdTreeTests.java │ ├── LCPArrayTest.java │ ├── ListTests.java │ ├── LowestCommonAncestorTest.java │ ├── MatrixTests.java │ ├── PatriciaTreeTests.java │ ├── QuadTreeTests.java │ ├── QueueTests.java │ ├── RadixTrieTests.java │ ├── RedBlackTreeTests.java │ ├── SegmentTreeTests.java │ ├── SkipListMapTests.java │ ├── SkipListTests.java │ ├── SplayTreeTests.java │ ├── StackTests.java │ ├── SuffixArrayTest.java │ ├── SuffixTreeTests.java │ ├── SuffixTrieTests.java │ ├── TernarySearchTreeTests.java │ ├── TreapTests.java │ ├── TreeMapTests.java │ ├── TrieMapTests.java │ ├── TrieTests.java │ └── common │ │ ├── HeapTest.java │ │ ├── IteratorTest.java │ │ ├── JavaCollectionTest.java │ │ ├── JavaMapTest.java │ │ ├── ListIteratorTest.java │ │ ├── ListTest.java │ │ ├── MapTest.java │ │ ├── QueueTest.java │ │ ├── SetTest.java │ │ ├── StackTest.java │ │ ├── SuffixTreeTest.java │ │ ├── TreeTest.java │ │ └── Utils.java └── timing │ ├── DataStructuresTiming.java │ └── SpatialDataStructuresTiming.java ├── graph └── test │ ├── BreadthFirstTraversalTest.java │ ├── DepthFirstTraversalTest.java │ ├── EdmondsKarpTest.java │ ├── Graphs.java │ ├── PushRelabelTest.java │ └── TurboMatchingTest.java ├── mathematics ├── test │ ├── CoprimesTest.java │ ├── DiscreteLogarithmTest.java │ ├── ExponentiationTest.java │ ├── GCDTest.java │ ├── LUDecompositionTest.java │ ├── MathematicsTest.java │ ├── ModularArithmeticTest.java │ ├── PermutationsTest.java │ └── RamerDouglasPeuckerTest.java └── timing │ ├── ExponentiationTiming.java │ ├── GCDTiming.java │ └── MathematicsTiming.java ├── numbers ├── test │ └── Numbers.java └── timing │ └── NumbersTiming.java ├── search ├── test │ └── Search.java └── timing │ └── SearchTiming.java ├── sequence ├── test │ └── Sequences.java └── timing │ └── SequencesTiming.java ├── sorts ├── test │ └── Sorts.java └── timing │ └── SortsTiming.java └── strings ├── test ├── KnuthMorrisPrattTests.java ├── ManacherTests.java ├── StringRotation.java └── Strings.java └── timing └── StringsTiming.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /build/ 3 | /dist/ 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JavaAlgorithmsImplementation 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Thu Dec 15 14:40:25 EST 2011 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.6 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_script: 2 | - sudo apt-get install ant-optional 3 | - export OPTS="-server -Xmx3072M" 4 | - export JAVA_OPTS="${JAVA_OPTS} ${OPTS}" 5 | - export ANT_OPTS="${ANT_OPTS} ${OPTS}" 6 | - echo $JAVA_OPTS 7 | - echo $ANT_OPTS 8 | 9 | dist: trusty 10 | 11 | language: java 12 | 13 | jdk: 14 | - oraclejdk9 15 | - oraclejdk8 16 | # - oraclejdk7 17 | # - oraclejdk6 18 | 19 | # - openjdk9 20 | - openjdk8 21 | - openjdk7 22 | # - openjdk6 23 | 24 | env: 25 | - TEST_SUITE=run_tests 26 | # - TEST_SUITE=mathematics 27 | # - TEST_SUITE=numbers 28 | # - TEST_SUITE=search 29 | # - TEST_SUITE=sequences 30 | # - TEST_SUITE=strings 31 | # - TEST_SUITE=data_structures 32 | # - TEST_SUITE=sorts 33 | 34 | script: "ant $TEST_SUITE" 35 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | #### By submitting this pull request I confirm I've read and complied with the below requirements. 11 | 12 | - [ ] I have read the [Contribution guidelines](CONTRIBUTING.md) and I am confident that my PR reflects them. 13 | - [ ] I have followed the [coding guidelines](CONTRIBUTING.md#cs) for this project. 14 | - [ ] My code follows the [skeleton code structure](CONTRIBUTING.md#sample). 15 | - [ ] This pull request has a descriptive title. For example, `Added {Algorithm/DS name} [{Language}]`, not `Update README.md` or `Added new code`. 16 | -------------------------------------------------------------------------------- /lib/junit-4_4.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phishman3579/java-algorithms-implementation/f2d115704691e8e4f6cfe490231d0adb0c3ce7d0/lib/junit-4_4.3.1.jar -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/LCPArray.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * In computer science, the longest common prefix array (LCP array) is an auxiliary 7 | * data structure to the suffix array. It stores the lengths of the longest common 8 | * prefixes (LCPs) between all pairs of consecutive suffixes in a sorted suffix array. 9 | *

10 | * @see LCP Array (Wikipedia) 11 | *
12 | * @author Jakub Szarawarski 13 | * @author Justin Wetherell 14 | */ 15 | public class LCPArray { 16 | 17 | private static final char DEFAULT_END_SEQ_CHAR = '$'; 18 | 19 | private final char endSeqChar; 20 | 21 | private SuffixArray suffixArray; 22 | private ArrayList lcp; 23 | 24 | public LCPArray(C sequence){ 25 | this(sequence, DEFAULT_END_SEQ_CHAR); 26 | } 27 | 28 | public LCPArray(C sequence, char endChar) { 29 | endSeqChar = endChar; 30 | suffixArray = new SuffixArray(sequence, endSeqChar); 31 | } 32 | 33 | public ArrayList getLCPArray() { 34 | if (lcp == null) 35 | LCPAlgorithm(); 36 | return lcp; 37 | } 38 | 39 | private void LCPAlgorithm() { 40 | final ArrayList LCPR = getLCPR(); 41 | getLCPfromLCPR(LCPR); 42 | } 43 | 44 | private ArrayList getLCPR() { 45 | final ArrayList KMRArrayList = suffixArray.getKMRarray(); 46 | final ArrayList suffixArrayList = suffixArray.getSuffixArray(); 47 | final String string = suffixArray.getString(); 48 | final int length = KMRArrayList.size(); 49 | final ArrayList LCPR = new ArrayList(); // helper array, LCP[i] = LCPR[suffixArray[i]] 50 | 51 | int startingValue = 0; 52 | for (int i=0; i 0 ? LCPRValue-1 : 0; 63 | } 64 | } 65 | 66 | return LCPR; 67 | } 68 | 69 | private void getLCPfromLCPR(ArrayList LCPR) { 70 | final ArrayList suffixArrayList = suffixArray.getSuffixArray(); 71 | final int length = suffixArrayList.size(); 72 | 73 | lcp = new ArrayList(); 74 | lcp.add(null); //no value for LCP[0] 75 | for (int i=1; i 11 | * @see Heap (Wikipedia) 12 | *
13 | * @author Justin Wetherell 14 | */ 15 | public interface IHeap { 16 | 17 | /** 18 | * Add value to the heap. 19 | * 20 | * @param value to add to the heap. 21 | * @return True if added to the heap. 22 | */ 23 | public boolean add(T value); 24 | 25 | /** 26 | * Get the value of the head node from the heap. 27 | * 28 | * @return value of the head node. 29 | */ 30 | public T getHeadValue(); 31 | 32 | /** 33 | * Remove the head node from the heap. 34 | * 35 | * @return value of the head node. 36 | */ 37 | public T removeHead(); 38 | 39 | /** 40 | * Remove the value from the heap. 41 | * 42 | * @param value to remove from heap. 43 | * @return True if value was removed form the heap; 44 | */ 45 | public T remove(T value); 46 | 47 | /** 48 | * Clear the entire heap. 49 | */ 50 | public void clear(); 51 | 52 | /** 53 | * Does the value exist in the heap. Warning this is a O(n) operation. 54 | * 55 | * @param value to locate in the heap. 56 | * @return True if the value is in heap. 57 | */ 58 | public boolean contains(T value); 59 | 60 | /** 61 | * Get size of the heap. 62 | * 63 | * @return size of the heap. 64 | */ 65 | public int size(); 66 | 67 | /** 68 | * Validate the heap according to the invariants. 69 | * 70 | * @return True if the heap is valid. 71 | */ 72 | public boolean validate(); 73 | 74 | /** 75 | * Get this Heap as a Java compatible Collection 76 | * 77 | * @return Java compatible Collection 78 | */ 79 | public java.util.Collection toCollection(); 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/IList.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | /** 4 | * A list or sequence is an abstract data type that implements an ordered 5 | * collection of values, where the same value may occur more than once. 6 | *

7 | * @see List (Wikipedia) 8 | *
9 | * @author Justin Wetherell 10 | */ 11 | public interface IList { 12 | 13 | /** 14 | * Add value to list. 15 | * 16 | * @param value to add. 17 | * @return True if added. 18 | */ 19 | public boolean add(T value); 20 | 21 | /** 22 | * Remove value from list. 23 | * 24 | * @param value to remove. 25 | * @return True if removed. 26 | */ 27 | public boolean remove(T value); 28 | 29 | /** 30 | * Clear the entire list. 31 | */ 32 | public void clear(); 33 | 34 | /** 35 | * Does the list contain value. 36 | * 37 | * @param value to search list for. 38 | * @return True if list contains value. 39 | */ 40 | public boolean contains(T value); 41 | 42 | /** 43 | * Size of the list. 44 | * 45 | * @return size of the list. 46 | */ 47 | public int size(); 48 | 49 | /** 50 | * Validate the list according to the invariants. 51 | * 52 | * @return True if the list is valid. 53 | */ 54 | public boolean validate(); 55 | 56 | /** 57 | * Get this List as a Java compatible List 58 | * 59 | * @return Java compatible List 60 | */ 61 | public java.util.List toList(); 62 | 63 | /** 64 | * Get this List as a Java compatible Collection 65 | * 66 | * @return Java compatible Collection 67 | */ 68 | public java.util.Collection toCollection(); 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/IMap.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | /** 4 | * In computer science, an associative array, map, or dictionary is an abstract 5 | * data type composed of a collection of (key, value) pairs, such that each possible 6 | * key appears at most once in the collection. 7 | *

8 | * @see Associative Array (Wikipedia) 9 | *
10 | * @author Justin Wetherell 11 | */ 12 | public interface IMap { 13 | 14 | /** 15 | * Put key->value pair in the map. 16 | * 17 | * @param key to be inserted. 18 | * @param value to be inserted. 19 | * @return V previous value or null if none. 20 | */ 21 | public V put(K key, V value); 22 | 23 | /** 24 | * Get value for key. 25 | * 26 | * @param key to get value for. 27 | * @return value mapped to key. 28 | */ 29 | public V get(K key); 30 | 31 | /** 32 | * Remove key and value from map. 33 | * 34 | * @param key to remove from the map. 35 | * @return True if removed or False if not found. 36 | */ 37 | public V remove(K key); 38 | 39 | /** 40 | * Clear the entire map. 41 | */ 42 | public void clear(); 43 | 44 | /** 45 | * Does the map contain the key. 46 | * 47 | * @param key to locate in the map. 48 | * @return True if key is in the map. 49 | */ 50 | public boolean contains(K key); 51 | 52 | /** 53 | * Number of key/value pairs in the hash map. 54 | * 55 | * @return number of key/value pairs. 56 | */ 57 | public int size(); 58 | 59 | /** 60 | * Validate the map according to the invariants. 61 | * 62 | * @return True if the map is valid. 63 | */ 64 | public boolean validate(); 65 | 66 | /** 67 | * Wraps this map in a Java compatible Map 68 | * 69 | * @return Java compatible Map 70 | */ 71 | public java.util.Map toMap(); 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/IQueue.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | /** 4 | * A queue is a particular kind of abstract data type or collection in 5 | * which the entities in the collection are kept in order and the principal (or 6 | * only) operations on the collection are the addition of entities to the rear 7 | * terminal position and removal of entities from the front terminal position. 8 | * This makes the queue a First-In-First-Out (FIFO) data structure. In a FIFO 9 | * data structure, the first element added to the queue will be the first one to 10 | * be removed. 11 | *

12 | * @see Queue (Wikipedia) 13 | *
14 | * @author Justin Wetherell 15 | */ 16 | public interface IQueue { 17 | 18 | /** 19 | * Add a value to the beginning of the queue. 20 | * 21 | * @param value to add to queue. 22 | * @return True if added to queue. 23 | */ 24 | public boolean offer(T value); 25 | 26 | /** 27 | * Remove a value from the tail of the queue. 28 | * 29 | * @return value from the tail of the queue. 30 | */ 31 | public T poll(); 32 | 33 | /** 34 | * Get but do not remove tail of the queue. 35 | * 36 | * @return value from the tail of the queue. 37 | */ 38 | public T peek(); 39 | 40 | /** 41 | * Remove the value from the queue. 42 | * 43 | * @param value to remove from the queue. 44 | * @return True if the value was removed from the queue. 45 | */ 46 | public boolean remove(T value); 47 | 48 | /** 49 | * Clear the entire queue. 50 | */ 51 | public void clear(); 52 | 53 | /** 54 | * Does the queue contain the value. 55 | * 56 | * @param value to find in the queue. 57 | * @return True if the queue contains the value. 58 | */ 59 | public boolean contains(T value); 60 | 61 | /** 62 | * Get the size of the queue. 63 | * 64 | * @return size of the queue. 65 | */ 66 | public int size(); 67 | 68 | /** 69 | * Validate the queue according to the invariants. 70 | * 71 | * @return True if the queue is valid. 72 | */ 73 | public boolean validate(); 74 | 75 | /** 76 | * Get this Queue as a Java compatible Queue 77 | * 78 | * @return Java compatible Queue 79 | */ 80 | public java.util.Queue toQueue(); 81 | 82 | /** 83 | * Get this Queue as a Java compatible Collection 84 | * 85 | * @return Java compatible Collection 86 | */ 87 | public java.util.Collection toCollection(); 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/ISet.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | /** 4 | * In computer science, a set is an abstract data structure that can store certain values, without 5 | * any particular order, and no repeated values. It is a computer implementation of the mathematical 6 | * concept of a finite set. Unlike most other collection types, rather than retrieving a specific 7 | * element from a set, one typically tests a value for membership in a set. 8 | *

9 | * @see Set (Wikipedia) 10 | *
11 | * @author Justin Wetherell 12 | */ 13 | public interface ISet { 14 | 15 | /** 16 | * Add value to set. 17 | * 18 | * @param value to add. 19 | * @return True if added. 20 | */ 21 | public boolean add(T value); 22 | 23 | /** 24 | * Remove value from set. 25 | * 26 | * @param value to remove. 27 | * @return True if removed. 28 | */ 29 | public boolean remove(T value); 30 | 31 | /** 32 | * Clear the entire set. 33 | */ 34 | public void clear(); 35 | 36 | /** 37 | * Does the set contain value. 38 | * 39 | * @param value to search set for. 40 | * @return True if set contains value. 41 | */ 42 | public boolean contains(T value); 43 | 44 | /** 45 | * Size of the set. 46 | * 47 | * @return size of the set. 48 | */ 49 | public int size(); 50 | 51 | /** 52 | * Validate the set according to the invariants. 53 | * 54 | * @return True if the set is valid. 55 | */ 56 | public boolean validate(); 57 | 58 | /** 59 | * Get this Set as a Java compatible Set 60 | * 61 | * @return Java compatible Set 62 | */ 63 | public java.util.Set toSet(); 64 | 65 | /** 66 | * Get this Set as a Java compatible Collection 67 | * 68 | * @return Java compatible Collection 69 | */ 70 | public java.util.Collection toCollection(); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/IStack.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | /** 4 | * A stack is a last in, first out (LIFO) abstract data type and linear 5 | * data structure. A stack can have any abstract data type as an element, but is 6 | * characterized by two fundamental operations, called push and pop. The push 7 | * operation adds a new item to the top of the stack, or initializes the stack 8 | * if it is empty. If the stack is full and does not contain enough space to 9 | * accept the given item, the stack is then considered to be in an overflow 10 | * state. The pop operation removes an item from the top of the stack. 11 | *

12 | * @see Stack (Wikipedia) 13 | *
14 | * @author Justin Wetherell 15 | */ 16 | public interface IStack { 17 | 18 | /** 19 | * Push value on top of stack 20 | * 21 | * @param value to push on the stack. 22 | */ 23 | public boolean push(T value); 24 | 25 | /** 26 | * Pop the value from the top of stack. 27 | * 28 | * @return value popped off the top of the stack. 29 | */ 30 | public T pop(); 31 | 32 | /** 33 | * Peek the value from the top of stack. 34 | * 35 | * @return value popped off the top of the stack. 36 | */ 37 | public T peek(); 38 | 39 | /** 40 | * Remove value from stack. 41 | * 42 | * @param value to remove from stack. 43 | * @return True if value was removed. 44 | */ 45 | public boolean remove(T value); 46 | 47 | /** 48 | * Clear the entire stack. 49 | */ 50 | public void clear(); 51 | 52 | /** 53 | * Does stack contain object. 54 | * 55 | * @param value object to find in stack. 56 | * @return True is stack contains object. 57 | */ 58 | public boolean contains(T value); 59 | 60 | /** 61 | * Size of the stack. 62 | * 63 | * @return size of the stack. 64 | */ 65 | public int size(); 66 | 67 | /** 68 | * Validate the stack according to the invariants. 69 | * 70 | * @return True if the stack is valid. 71 | */ 72 | public boolean validate(); 73 | 74 | /** 75 | * Get this Stack as a Java compatible Queue 76 | * 77 | * @return Java compatible Queue 78 | */ 79 | public java.util.Queue toLifoQueue(); 80 | 81 | /** 82 | * Get this Stack as a Java compatible Collection 83 | * 84 | * @return Java compatible Collection 85 | */ 86 | public java.util.Collection toCollection(); 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/ISuffixTree.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * In computer science, a suffix tree (also called PAT tree or, in an earlier form, position tree) is a compressed trie 7 | * containing all the suffixes of the given text as their keys and positions in the text as their values. Suffix trees 8 | * allow particularly fast implementations of many important string operations. 9 | *

10 | * @see Suffix Tree (Wikipedia) 11 | *
12 | * @author Justin Wetherell 13 | */ 14 | public interface ISuffixTree { 15 | 16 | /** 17 | * Does the sub-sequence exist in the suffix tree. 18 | * 19 | * @param sub-sequence to locate in the tree. 20 | * @return True if the sub-sequence exist in the tree. 21 | */ 22 | public boolean doesSubStringExist(C sub); 23 | 24 | /** 25 | * Get all the suffixes in the tree. 26 | * 27 | * @return set of suffixes in the tree. 28 | */ 29 | public Set getSuffixes(); 30 | } 31 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/data_structures/interfaces/ITree.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.interfaces; 2 | 3 | /** 4 | * A tree can be defined recursively (locally) as a collection of nodes (starting at a root node), 5 | * where each node is a data structure consisting of a value, together with a list of nodes (the "children"), 6 | * with the constraints that no node is duplicated. A tree can be defined abstractly as a whole (globally) 7 | * as an ordered tree, with a value assigned to each node. 8 | *

9 | * @see Tree (Wikipedia) 10 | *
11 | * @author Justin Wetherell 12 | */ 13 | public interface ITree { 14 | 15 | /** 16 | * Add value to the tree. Tree can contain multiple equal values. 17 | * 18 | * @param value to add to the tree. 19 | * @return True if successfully added to tree. 20 | */ 21 | public boolean add(T value); 22 | 23 | /** 24 | * Remove first occurrence of value in the tree. 25 | * 26 | * @param value to remove from the tree. 27 | * @return T value removed from tree. 28 | */ 29 | public T remove(T value); 30 | 31 | /** 32 | * Clear the entire stack. 33 | */ 34 | public void clear(); 35 | 36 | /** 37 | * Does the tree contain the value. 38 | * 39 | * @param value to locate in the tree. 40 | * @return True if tree contains value. 41 | */ 42 | public boolean contains(T value); 43 | 44 | /** 45 | * Get number of nodes in the tree. 46 | * 47 | * @return Number of nodes in the tree. 48 | */ 49 | public int size(); 50 | 51 | /** 52 | * Validate the tree according to the invariants. 53 | * 54 | * @return True if the tree is valid. 55 | */ 56 | public boolean validate(); 57 | 58 | /** 59 | * Get Tree as a Java compatible Collection 60 | * 61 | * @return Java compatible Collection 62 | */ 63 | public java.util.Collection toCollection(); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/ConnectedComponents.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import com.jwetherell.algorithms.data_structures.Graph; 9 | import com.jwetherell.algorithms.data_structures.Graph.Edge; 10 | import com.jwetherell.algorithms.data_structures.Graph.Vertex; 11 | 12 | /** 13 | * In graph theory, a connected component (or just component) of an undirected graph is a subgraph in which any two vertices are connected to each 14 | * other by paths, and which is connected to no additional vertices in the supergraph. A vertex with no incident edges is itself a connected 15 | * component. A graph that is itself connected has exactly one connected component, consisting of the whole graph. 16 | *

17 | * @see Connected Components (Wikipedia) 18 | *
19 | * @author Justin Wetherell 20 | */ 21 | public class ConnectedComponents { 22 | 23 | private ConnectedComponents() { } 24 | 25 | /** 26 | * Finds the connected components subsets of the Graph. 27 | * 28 | * @param graph 29 | * to find connected components. 30 | * @return List of connected components in the Graph. 31 | */ 32 | public static final > List>> getConnectedComponents(Graph graph) { 33 | if (graph == null) 34 | throw new IllegalArgumentException("Graph is NULL."); 35 | 36 | if (graph.getType() != Graph.TYPE.DIRECTED) 37 | throw new IllegalArgumentException("Cannot perform a connected components search on a non-directed graph. graph type = "+graph.getType()); 38 | 39 | final Map,Integer> map = new HashMap,Integer>(); 40 | final List>> list = new ArrayList>>(); 41 | 42 | int c = 0; 43 | for (Vertex v : graph.getVertices()) 44 | if (map.get(v) == null) 45 | visit(map, list, v, c++); 46 | return list; 47 | } 48 | 49 | private static final > void visit(Map,Integer> map, List>> list, Vertex v, int c) { 50 | map.put(v, c); 51 | 52 | List> r = null; 53 | if (c == list.size()) { 54 | r = new ArrayList>(); 55 | list.add(r); 56 | } else { 57 | r = list.get(c); 58 | } 59 | r.add(v); 60 | 61 | if (v.getEdges().size() > 0) { 62 | boolean found = false; 63 | for (Edge e : v.getEdges()) { 64 | final Vertex to = e.getToVertex(); 65 | if (map.get(to) == null) { 66 | visit(map, list, to, c); 67 | found = true; 68 | } 69 | if (found) 70 | break; 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/CycleDetection.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | import java.util.HashSet; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import com.jwetherell.algorithms.data_structures.Graph; 8 | 9 | /** 10 | * In computer science, cycle detection or cycle finding is the algorithmic problem of finding a cycle in a sequence of iterated function values. 11 | *

12 | * @see Cycle Detection (Wikipedia) 13 | *
14 | * @author Justin Wetherell 15 | */ 16 | public class CycleDetection { 17 | 18 | private CycleDetection() { } 19 | 20 | /** 21 | * Cycle detection on a unidrected graph. 22 | * 23 | * @param graph Graph 24 | * @return true if a cycle exists 25 | */ 26 | public static > boolean detect(Graph graph) { 27 | if (graph == null) 28 | throw new IllegalArgumentException("Graph is NULL."); 29 | 30 | if (graph.getType() != Graph.TYPE.UNDIRECTED) 31 | throw new IllegalArgumentException("Graph is needs to be Undirected."); 32 | 33 | final Set> visitedVerticies = new HashSet>(); 34 | final Set> visitedEdges = new HashSet>(); 35 | 36 | final List> verticies = graph.getVertices(); 37 | if (verticies == null || verticies.size() == 0) 38 | return false; 39 | 40 | // Select the zero-ith element as the root 41 | final Graph.Vertex root = verticies.get(0); 42 | return depthFirstSearch(root, visitedVerticies, visitedEdges); 43 | } 44 | 45 | private static final > boolean depthFirstSearch(Graph.Vertex vertex, Set> visitedVerticies, Set> visitedEdges) { 46 | if (!visitedVerticies.contains(vertex)) { 47 | // Found an unvisited, add to the set 48 | visitedVerticies.add(vertex); 49 | 50 | final List> edges = vertex.getEdges(); 51 | if (edges != null) { 52 | // Follow each unvisited edge, visit the vertex the edge connects to. 53 | for (Graph.Edge edge : edges) { 54 | final Graph.Vertex to = edge.getToVertex(); 55 | boolean result = false; 56 | if (to != null && !visitedEdges.contains(edge)) { 57 | visitedEdges.add(edge); 58 | 59 | final Graph.Edge recip = new Graph.Edge(edge.getCost(), edge.getToVertex(), edge.getFromVertex()); 60 | visitedEdges.add(recip); 61 | 62 | result = depthFirstSearch(to, visitedVerticies, visitedEdges); 63 | } 64 | if (result == true) 65 | return result; 66 | } 67 | } 68 | } else { 69 | // visited 70 | return true; 71 | } 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/EdmondsKarp.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | 4 | import java.util.ArrayDeque; 5 | import java.util.Queue; 6 | 7 | /** 8 | * In computer science, the Edmonds–Karp algorithm is an implementation of the Ford–Fulkerson method for 9 | * computing the maximum flow in a flow network in O(V*E^2) time. 10 | *

11 | * @see Edmonds-Karp Algorithm (Wikipedia) 12 | *
13 | * @author Mateusz Cianciara 14 | * @author Justin Wetherell 15 | */ 16 | public class EdmondsKarp { 17 | 18 | private long[][] flow; //max flow beetween i and j verticles 19 | private long[][] capacity; // edge capacity 20 | private int[] parent; //parent 21 | private boolean[] visited; //just for checking if visited 22 | @SuppressWarnings("unused") 23 | private int n, m; 24 | 25 | public EdmondsKarp(int numOfVerticles, int numOfEdges) { 26 | this.n = numOfVerticles; 27 | this.m = numOfEdges; 28 | this.flow = new long[n][n]; 29 | this.capacity = new long[n][n]; 30 | this.parent = new int[n]; 31 | this.visited = new boolean[n]; 32 | } 33 | 34 | public void addEdge(int from, int to, long capacity) { 35 | assert capacity >= 0; 36 | this.capacity[from][to] += capacity; 37 | } 38 | 39 | /** 40 | * Get maximum flow. 41 | * 42 | * @param s source 43 | * @param t target 44 | * @return maximum flow 45 | */ 46 | public long getMaxFlow(int s, int t) { 47 | while (true) { 48 | final Queue Q = new ArrayDeque(); 49 | Q.add(s); 50 | 51 | for (int i = 0; i < this.n; ++i) 52 | visited[i] = false; 53 | visited[s] = true; 54 | 55 | boolean check = false; 56 | int current; 57 | while (!Q.isEmpty()) { 58 | current = Q.peek(); 59 | if (current == t) { 60 | check = true; 61 | break; 62 | } 63 | Q.remove(); 64 | for (int i = 0; i < n; ++i) { 65 | if (!visited[i] && capacity[current][i] > flow[current][i]) { 66 | visited[i] = true; 67 | Q.add(i); 68 | parent[i] = current; 69 | } 70 | } 71 | } 72 | if (check == false) 73 | break; 74 | 75 | long temp = capacity[parent[t]][t] - flow[parent[t]][t]; 76 | for (int i = t; i != s; i = parent[i]) 77 | temp = Math.min(temp, (capacity[parent[i]][i] - flow[parent[i]][i])); 78 | 79 | for (int i = t; i != s; i = parent[i]) { 80 | flow[parent[i]][i] += temp; 81 | flow[i][parent[i]] -= temp; 82 | } 83 | } 84 | 85 | long result = 0; 86 | for (int i = 0; i < n; ++i) 87 | result += flow[s][i]; 88 | return result; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/FloydWarshall.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import com.jwetherell.algorithms.data_structures.Graph; 8 | 9 | /** 10 | * Floyd–Warshall algorithm is a graph analysis algorithm for finding shortest 11 | * paths in a weighted graph (with positive or negative edge weights). 12 | *

13 | * Worst case: O(V^3) 14 | *

15 | * @see Floyd-Warshall Algorithm (Wikipedia) 16 | *
17 | * @author Justin Wetherell 18 | */ 19 | public class FloydWarshall { 20 | 21 | private FloydWarshall() { } 22 | 23 | public static Map, Map, Integer>> getAllPairsShortestPaths(Graph graph) { 24 | if (graph == null) 25 | throw (new NullPointerException("Graph must be non-NULL.")); 26 | 27 | final List> vertices = graph.getVertices(); 28 | 29 | final int[][] sums = new int[vertices.size()][vertices.size()]; 30 | for (int i = 0; i < sums.length; i++) { 31 | for (int j = 0; j < sums[i].length; j++) { 32 | sums[i][j] = Integer.MAX_VALUE; 33 | } 34 | } 35 | 36 | final List> edges = graph.getEdges(); 37 | for (Graph.Edge e : edges) { 38 | final int indexOfFrom = vertices.indexOf(e.getFromVertex()); 39 | final int indexOfTo = vertices.indexOf(e.getToVertex()); 40 | sums[indexOfFrom][indexOfTo] = e.getCost(); 41 | } 42 | 43 | for (int k = 0; k < vertices.size(); k++) { 44 | for (int i = 0; i < vertices.size(); i++) { 45 | for (int j = 0; j < vertices.size(); j++) { 46 | if (i == j) { 47 | sums[i][j] = 0; 48 | } else { 49 | final int ijCost = sums[i][j]; 50 | final int ikCost = sums[i][k]; 51 | final int kjCost = sums[k][j]; 52 | final int summed = (ikCost != Integer.MAX_VALUE && 53 | kjCost != Integer.MAX_VALUE) ? 54 | (ikCost + kjCost) 55 | : 56 | Integer.MAX_VALUE; 57 | if (ijCost > summed) 58 | sums[i][j] = summed; 59 | } 60 | } 61 | } 62 | } 63 | 64 | final Map, Map, Integer>> allShortestPaths = new HashMap, Map, Integer>>(); 65 | for (int i = 0; i < sums.length; i++) { 66 | for (int j = 0; j < sums[i].length; j++) { 67 | final Graph.Vertex from = vertices.get(i); 68 | final Graph.Vertex to = vertices.get(j); 69 | 70 | Map, Integer> map = allShortestPaths.get(from); 71 | if (map == null) 72 | map = new HashMap, Integer>(); 73 | 74 | final int cost = sums[i][j]; 75 | if (cost != Integer.MAX_VALUE) 76 | map.put(to, cost); 77 | allShortestPaths.put(from, map); 78 | } 79 | } 80 | return allShortestPaths; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/Kruskal.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | import com.jwetherell.algorithms.data_structures.Graph; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * Kruskal's minimum spanning tree. Only works on undirected graphs. It finds a 9 | * subset of the edges that forms a tree that includes every vertex, where the 10 | * total weight of all the edges in the tree is minimized. 11 | *

12 | * @see Kruskal's Algorithm (Wikipedia) 13 | *
14 | * @author Bartlomiej Drozd 15 | * @author Justin Wetherell 16 | */ 17 | public class Kruskal { 18 | 19 | private Kruskal() { } 20 | 21 | public static Graph.CostPathPair getMinimumSpanningTree(Graph graph) { 22 | if (graph == null) 23 | throw (new NullPointerException("Graph must be non-NULL.")); 24 | 25 | // Kruskal's algorithm only works on undirected graphs 26 | if (graph.getType() == Graph.TYPE.DIRECTED) 27 | throw (new IllegalArgumentException("Undirected graphs only.")); 28 | 29 | int cost = 0; 30 | final List> path = new ArrayList>(); 31 | 32 | // Prepare data to store information which part of tree given vertex is 33 | HashMap, HashSet>> membershipMap = new HashMap, HashSet>>(); 34 | for (Graph.Vertex v : graph.getVertices()) { 35 | HashSet> set = new HashSet>(); 36 | set.add(v); 37 | membershipMap.put(v, set); 38 | } 39 | 40 | // We make queue of edges to consider all of them, starting with edge with the lowest cost, 41 | // it is important that Edge's class comparator is not natural (ex. sorting is from the biggest to the lowest) 42 | PriorityQueue> edgeQueue = new PriorityQueue>(graph.getEdges()); 43 | 44 | while (!edgeQueue.isEmpty()) { 45 | Graph.Edge edge = edgeQueue.poll(); 46 | 47 | // If from vertex and to vertex are from different parts of tree then add this edge to result and union vertices' parts 48 | if (!isTheSamePart(edge.getFromVertex(), edge.getToVertex(), membershipMap)) { 49 | union(edge.getFromVertex(), edge.getToVertex(), membershipMap); 50 | path.add(edge); 51 | cost += edge.getCost(); 52 | } 53 | } 54 | 55 | 56 | return (new Graph.CostPathPair(cost, path)); 57 | } 58 | 59 | private static boolean isTheSamePart(Graph.Vertex v1, Graph.Vertex v2, HashMap, HashSet>> membershipMap) { 60 | return membershipMap.get(v1) == membershipMap.get(v2); 61 | } 62 | 63 | private static void union(Graph.Vertex v1, Graph.Vertex v2, HashMap, HashSet>> membershipMap) { 64 | HashSet> firstSet = membershipMap.get(v1); //first set is the bigger set 65 | HashSet> secondSet = membershipMap.get(v2); 66 | 67 | // we want to include smaller set into bigger, so second set cannot be bigger than first 68 | if (secondSet.size() > firstSet.size()) { 69 | HashSet> tempSet = firstSet; 70 | firstSet = secondSet; 71 | secondSet = tempSet; 72 | } 73 | 74 | // changing part membership of each vertex from smaller set 75 | for (Graph.Vertex v : secondSet) { 76 | membershipMap.put(v, firstSet); 77 | } 78 | 79 | // adding all vertices from smaller set to bigger one 80 | firstSet.addAll(secondSet); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/Prim.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.PriorityQueue; 7 | import java.util.Queue; 8 | import java.util.Set; 9 | 10 | import com.jwetherell.algorithms.data_structures.Graph; 11 | 12 | /** 13 | * Prim's minimum spanning tree. Only works on undirected graphs. It finds a 14 | * subset of the edges that forms a tree that includes every vertex, where the 15 | * total weight of all the edges in the tree is minimized. 16 | *

17 | * @see Prim's Minimum Spanning Tree (Wikipedia) 18 | *
19 | * @author Justin Wetherell 20 | */ 21 | public class Prim { 22 | 23 | private Prim() { } 24 | 25 | public static Graph.CostPathPair getMinimumSpanningTree(Graph graph, Graph.Vertex start) { 26 | if (graph == null) 27 | throw (new NullPointerException("Graph must be non-NULL.")); 28 | 29 | // Prim's algorithm only works on undirected graphs 30 | if (graph.getType() == Graph.TYPE.DIRECTED) 31 | throw (new IllegalArgumentException("Undirected graphs only.")); 32 | 33 | int cost = 0; 34 | 35 | final Set> unvisited = new HashSet>(); 36 | unvisited.addAll(graph.getVertices()); 37 | unvisited.remove(start); // O(1) 38 | 39 | final List> path = new ArrayList>(); 40 | final Queue> edgesAvailable = new PriorityQueue>(); 41 | 42 | Graph.Vertex vertex = start; 43 | while (!unvisited.isEmpty()) { 44 | // Add all edges to unvisited vertices 45 | for (Graph.Edge e : vertex.getEdges()) { 46 | if (unvisited.contains(e.getToVertex())) 47 | edgesAvailable.add(e); 48 | } 49 | 50 | // Remove the lowest cost edge 51 | final Graph.Edge e = edgesAvailable.remove(); 52 | cost += e.getCost(); 53 | path.add(e); // O(1) 54 | 55 | vertex = e.getToVertex(); 56 | unvisited.remove(vertex); // O(1) 57 | } 58 | 59 | return (new Graph.CostPathPair(cost, path)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/graph/TopologicalSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.jwetherell.algorithms.data_structures.Graph; 7 | 8 | /** 9 | * In computer science, a topological sort (sometimes abbreviated topsort or 10 | * toposort) or topological ordering of a directed graph is a linear ordering of 11 | * its vertices such that, for every edge uv, u comes before v in the ordering. 12 | *

13 | * @see Topological Sort (Wikipedia) 14 | *
15 | * @author Justin Wetherell 16 | */ 17 | public class TopologicalSort { 18 | 19 | private TopologicalSort() { } 20 | 21 | /** 22 | * Performs a topological sort on a directed graph. Returns NULL if a cycle is detected. 23 | * 24 | * Note: This should NOT change the state of the graph parameter. 25 | * 26 | * @param graph 27 | * @return Sorted List of Vertices or NULL if graph has a cycle 28 | */ 29 | public static final List> sort(Graph graph) { 30 | if (graph == null) 31 | throw new IllegalArgumentException("Graph is NULL."); 32 | 33 | if (graph.getType() != Graph.TYPE.DIRECTED) 34 | throw new IllegalArgumentException("Cannot perform a topological sort on a non-directed graph. graph type = "+graph.getType()); 35 | 36 | // clone to prevent changes the graph parameter's state 37 | final Graph clone = new Graph(graph); 38 | final List> sorted = new ArrayList>(); 39 | final List> noOutgoing = new ArrayList>(); 40 | 41 | final List> edges = new ArrayList>(); 42 | edges.addAll(clone.getEdges()); 43 | 44 | // Find all the vertices which have no outgoing edges 45 | for (Graph.Vertex v : clone.getVertices()) { 46 | if (v.getEdges().size() == 0) 47 | noOutgoing.add(v); 48 | } 49 | 50 | // While we still have vertices which have no outgoing edges 51 | while (noOutgoing.size() > 0) { 52 | final Graph.Vertex current = noOutgoing.remove(0); 53 | sorted.add(current); 54 | 55 | // Go thru each edge, if it goes to the current vertex then remove it. 56 | int i = 0; 57 | while (i < edges.size()) { 58 | final Graph.Edge e = edges.get(i); 59 | final Graph.Vertex from = e.getFromVertex(); 60 | final Graph.Vertex to = e.getToVertex(); 61 | // Found an edge to the current vertex, remove it. 62 | if (to.equals(current)) { 63 | edges.remove(e); 64 | // Remove the reciprocal edge 65 | from.getEdges().remove(e); 66 | } else { 67 | i++; 68 | } 69 | // Removed all edges from 'from' vertex, add it to the onOutgoing list 70 | if (from.getEdges().size() == 0) 71 | noOutgoing.add(from); 72 | } 73 | } 74 | // If we have processed all connected vertices and there are edges remaining, graph has multiple connected components. 75 | if (edges.size() > 0) 76 | return null; 77 | return sorted; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/Coprimes.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | /** 4 | * In number theory, two integers a and b are said to be relatively prime, mutually prime, or coprime (also spelled 5 | * co-prime) if the only positive integer that divides both of them is 1. That is, the only common positive factor 6 | * of the two numbers is 1. This is equivalent to their greatest common divisor being 1. 7 | *

8 | * @see Mutually Prime / Co-prime (Wikipedia) 9 | *
10 | * @author Szymon Stankiewicz 11 | * @author Justin Wetherell 12 | */ 13 | public class Coprimes { 14 | 15 | private Coprimes() { } 16 | 17 | /** 18 | * 19 | * Euler's totient function. Because this function is multiplicative such implementation is possible. 20 | *

21 | * Time complexity: O(sqrt(n)) 22 | *

23 | * @param n Long integer 24 | * @return number of coprimes smaller or equal to n 25 | */ 26 | public static long getNumberOfCoprimes(long n) { 27 | if(n < 1) 28 | return 0; 29 | long res = 1; 30 | for(int i = 2; i*i <= n; i++) { 31 | int times = 0; 32 | while(n%i == 0) { 33 | res *= (times > 0 ? i : i-1); 34 | n /= i; 35 | times++; 36 | } 37 | } 38 | if(n > 1) 39 | res *= n-1; 40 | return res; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | import java.util.HashMap; 4 | 5 | import static java.lang.Math.sqrt; 6 | 7 | /** 8 | * In mathematics, a discrete logarithm is an integer k exponent solving the equation bk = g, where b and g are 9 | * elements of a group. Discrete logarithms are thus the group-theoretic analogue of ordinary logarithms, which 10 | * solve the same equation for real numbers b and g, where b is the base of the logarithm and g is the value whose 11 | * logarithm is being taken. 12 | *

13 | * @see Discrete Logarithm (Wikipedia) 14 | *
15 | * @author Lucjan Rosłanowski 16 | * @author Justin Wetherell 17 | */ 18 | public class DiscreteLogarithm { 19 | 20 | public static final long NO_SOLUTION = -1; 21 | 22 | private static final HashMap set = new HashMap(); 23 | 24 | private DiscreteLogarithm() { } 25 | 26 | private static final long pow(long a, long x, long p) { 27 | if (x == 0) 28 | return 1; 29 | 30 | if (x == 1) 31 | return a % p; 32 | 33 | if (x % 2 != 0) 34 | return (a * pow(a, x - 1, p)) % p; 35 | 36 | final long temp = pow(a, x / 2, p) % p; 37 | return (temp * temp) % p; 38 | } 39 | 40 | private static final long getDiscreteLogarithm(HashMap set, long s, long a, long p) { 41 | for (long i = 0; i < s; ++i) { 42 | long el = pow(a, (i * s) % p, p); 43 | el = pow(el, p - 2, p); 44 | 45 | if (set.containsKey(el)) 46 | return i * s + set.get(el); 47 | } 48 | return NO_SOLUTION; 49 | } 50 | 51 | private static final void generateSet(long a, long b_1, long p, long s, HashMap set) { 52 | set.clear(); 53 | for (long i = 0; i < s; ++i) { 54 | final long first = (pow(a, i, p) * b_1) % p; 55 | if (!set.containsKey(first)) 56 | set.put(first, i); 57 | } 58 | } 59 | 60 | /** 61 | * Returns DiscreteLogarithm.NO_SOLUTION when a solution cannot be found 62 | */ 63 | public static final long countDiscreteLogarithm(final long a, final long b, final long p) { 64 | final long s = (long) sqrt(p) + 1; 65 | final long b_1 = pow(b, p - 2, p); 66 | 67 | generateSet(a, b_1, p, s, set); 68 | return getDiscreteLogarithm(set, s,a,p); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/Distance.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | public class Distance { 4 | 5 | private Distance() { } 6 | 7 | /* 8 | * Chess distance 9 | */ 10 | public static final long chebyshevDistance(long[] point1, long[] point2) { 11 | long x1 = point1[0]; 12 | long y1 = point1[1]; 13 | long x2 = point2[0]; 14 | long y2 = point2[1]; 15 | return Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2)); 16 | } 17 | 18 | public static final double squaredDistance(double x1, double y1, double x2, double y2) { 19 | double x = x1 - x2; 20 | double y = y1 - y2; 21 | double sqr = (x * x) + (y * y); 22 | return sqr; 23 | } 24 | 25 | public static final double euclideanDistance(double x1, double y1, double x2, double y2) { 26 | double x = Math.pow((x1 - x2), 2); 27 | double y = Math.pow((y1 - y2), 2); 28 | double sqrt = Math.sqrt(x + y); 29 | return sqrt; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/Division.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | public class Division { 4 | 5 | public static final long division(int a, int b) { 6 | long result = ((long) a) / ((long) b); 7 | return result; 8 | } 9 | 10 | public static final long divisionUsingLoop(int a, int b) { 11 | int absA = Math.abs(a); 12 | int absB = Math.abs(b); 13 | 14 | long temp = absA; 15 | long result = 0; 16 | while (temp >= 0) { 17 | temp -= absB; 18 | if (temp >= 0) 19 | result++; 20 | } 21 | return (a > 0 && b > 0 || a < 0 && b < 0) ? result : -result; 22 | } 23 | 24 | public static final long divisionUsingRecursion(int a, int b) { 25 | int absA = Math.abs(a); 26 | int absB = Math.abs(b); 27 | 28 | long result = 1; 29 | int diff = absA - absB; 30 | if (diff > 0 && diff <= 1) { 31 | return result; 32 | } else if (diff < 0) { 33 | return 0; 34 | } 35 | 36 | result += divisionUsingRecursion(diff, absB); 37 | return (a > 0 && b > 0 || a < 0 && b < 0) ? result : -result; 38 | } 39 | 40 | public static final long divisionUsingMultiplication(int a, int b) { 41 | int absA = Math.abs(a); 42 | int absB = Math.abs(b); 43 | 44 | int temp = absB; 45 | int counter = 0; 46 | while (temp <= absA) { 47 | temp = temp << 1; 48 | counter++; 49 | } 50 | absA -= absB << (counter - 1); 51 | long result = (long) Math.pow(2, counter - 1); 52 | if (absB <= absA) 53 | result += divisionUsingMultiplication(absA, absB); 54 | return (a > 0 && b > 0 || a < 0 && b < 0) ? result : -result; 55 | } 56 | 57 | public static final long divisionUsingShift(int a, int b) { 58 | int absA = Math.abs(a); 59 | int absB = Math.abs(b); 60 | int tempA, tempB, counter; 61 | 62 | long result = 0L; 63 | while (absA >= absB) { 64 | tempA = absA >> 1; // Right shift "a" 65 | tempB = absB; 66 | counter = 1; 67 | while (tempA >= tempB) { // Double "tempB" until it's larger than 68 | // "tempA" 69 | tempB <<= 1; 70 | counter <<= 1; // Double the counter 71 | } 72 | absA -= tempB; // Subtract "tempB" from "a" 73 | result += counter; // Add counter (2^number of left shifts) 74 | } 75 | return (a > 0 && b > 0 || a < 0 && b < 0) ? result : -result; 76 | } 77 | 78 | public static final long divisionUsingLogs(int a, int b) { 79 | long absA = Math.abs(a); 80 | long absB = Math.abs(b); 81 | double logBase10A = Math.log10(absA); 82 | double logBase10B = Math.log10(absB); 83 | double powOf10 = Math.pow(10, (logBase10A - logBase10B)); 84 | long result = (long) Math.floor(powOf10); 85 | return (a > 0 && b > 0 || a < 0 && b < 0) ? result : -result; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/Exponentiation.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | /** 4 | * Recursive function of exponentiation is just an implementation of definition. 5 | *

6 | * @see Exponentiation (Wikipedia) 7 | *

8 | * Complexity - O(N) where N is exponent. 9 | *

10 | * Fast exponentiation's complexity is O(lg N) 11 | *

12 | * @see Exponentiation by Squaring (Wikipedia) 13 | *
14 | * Modular exponentiation is similar. 15 | *

16 | * @see Modular Exponentiation (Wikipedia) 17 | *

18 | * This implementation is the fast version of this algorithm with a complexity of O(lg N) also 19 | *
20 | * @author Bartlomiej Drozd 21 | * @author Justin Wetherell 22 | */ 23 | public class Exponentiation { 24 | 25 | public static int recursiveExponentiation(int base, int exponent) { 26 | if (exponent == 0) 27 | return 1; 28 | if (exponent == 1) 29 | return base; 30 | 31 | return recursiveExponentiation(base, exponent - 1) * base; 32 | } 33 | 34 | public static int fastRecursiveExponentiation(int base, int exponent) { 35 | if (exponent == 0) 36 | return 1; 37 | if (exponent == 1) 38 | return base; 39 | 40 | final int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); 41 | if ((exponent % 2) == 0) 42 | return resultOnHalfExponent * resultOnHalfExponent; 43 | else 44 | return resultOnHalfExponent * resultOnHalfExponent * base; 45 | 46 | } 47 | 48 | public static int fastRecursiveExponentiationModulo(int base, int exponent, int mod) { 49 | if (exponent == 0) 50 | return 1; 51 | if (exponent == 1) 52 | return base; 53 | 54 | final int resultOnHalfExponent = fastRecursiveExponentiationModulo(base, exponent / 2, mod); 55 | if ((exponent % 2) == 0) 56 | return (resultOnHalfExponent * resultOnHalfExponent) % mod; 57 | else 58 | return (((resultOnHalfExponent * resultOnHalfExponent) % mod) * base) % mod; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/FastFourierTransform.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | import com.jwetherell.algorithms.numbers.Complex; 4 | 5 | /** 6 | * A fast Fourier transform (FFT) algorithm computes the discrete Fourier transform (DFT) of a sequence, or its inverse. 7 | * Fourier analysis converts a signal from its original domain (often time or space) to a representation in the frequency 8 | * domain and vice versa. An FFT rapidly computes such transformations by factorizing the DFT matrix into a product of 9 | * sparse (mostly zero) factors. 10 | *

11 | * @see Fast Fourier Transform (Wikipedia) 12 | *
13 | * @author Mateusz Cianciara 14 | * @author Justin Wetherell 15 | */ 16 | public class FastFourierTransform { 17 | 18 | private FastFourierTransform() { } 19 | 20 | /** 21 | * The Cooley–Tukey algorithm, named after J.W. Cooley and John Tukey, is the most common fast Fourier transform 22 | * (FFT) algorithm. It re-expresses the discrete Fourier transform (DFT) of an arbitrary composite size N = N1N2 23 | * in terms of N1 smaller DFTs of sizes N2, recursively, to reduce the computation time to O(N log N) for highly 24 | * composite N (smooth numbers). 25 | *

26 | * @see Cooley–Tukey Algorithm (Wikipedia) 27 | *
28 | * @param coefficients size must be power of 2 29 | */ 30 | public static void cooleyTukeyFFT(Complex[] coefficients) { 31 | final int size = coefficients.length; 32 | if (size <= 1) 33 | return; 34 | 35 | final Complex[] even = new Complex[size / 2]; 36 | final Complex[] odd = new Complex[size / 2]; 37 | for (int i = 0; i < size; i++) { 38 | if (i % 2 == 0) { 39 | even[i / 2] = coefficients[i]; 40 | } else { 41 | odd[(i - 1) / 2] = coefficients[i]; 42 | } 43 | } 44 | cooleyTukeyFFT(even); 45 | cooleyTukeyFFT(odd); 46 | for (int k = 0; k < size / 2; k++) { 47 | Complex t = Complex.polar(1.0, -2 * Math.PI * k / size).multiply(odd[k]); 48 | coefficients[k] = even[k].add(t); 49 | coefficients[k + size / 2] = even[k].sub(t); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/GreatestCommonDivisor.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | /** 4 | * In mathematics, the greatest common divisor (gcd) of two or more integers, when at least one of them is not 5 | * zero, is the largest positive integer that is a divisor of both numbers. 6 | *

7 | * @see Greatest Common Divisor (Wikipedia) 8 | *
9 | * @author Szymon Stankiewicz 10 | * @author Justin Wetherell 11 | */ 12 | public class GreatestCommonDivisor { 13 | 14 | /** 15 | * Calculate greatest common divisor of two numbers using recursion. 16 | *

17 | * Time complexity O(log(a+b)) 18 | *
19 | * @param a Long integer 20 | * @param b Long integer 21 | * @return greatest common divisor of a and b 22 | */ 23 | public static long gcdUsingRecursion(long a, long b) { 24 | a = Math.abs(a); 25 | b = Math.abs(b); 26 | return a == 0 ? b : gcdUsingRecursion(b%a, a); 27 | } 28 | 29 | /** 30 | * A much more efficient method is the Euclidean algorithm, which uses a division algorithm such as long division 31 | * in combination with the observation that the gcd of two numbers also divides their difference. 32 | *

33 | * @see Euclidean Algorithm (Wikipedia) 34 | */ 35 | public static final long gcdUsingEuclides(long x, long y) { 36 | long greater = x; 37 | long smaller = y; 38 | if (y > x) { 39 | greater = y; 40 | smaller = x; 41 | } 42 | 43 | long result = 0; 44 | while (true) { 45 | if (smaller == greater) { 46 | result = smaller; // smaller == greater 47 | break; 48 | } 49 | 50 | greater -= smaller; 51 | if (smaller > greater) { 52 | long temp = smaller; 53 | smaller = greater; 54 | greater = temp; 55 | } 56 | } 57 | return result; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/Knapsack.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * The knapsack problem or rucksack problem is a problem in combinatorial optimization: Given a set of items, each with a weight and a value, determine the number of each item to include in a 8 | * collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. It derives its name from the problem faced by someone who is constrained 9 | * by a fixed-size knapsack and must fill it with the most valuable items. 10 | *

11 | * @see Knapsack Problem (Wikipedia) 12 | *
13 | * @author Justin Wetherell 14 | */ 15 | public class Knapsack { 16 | 17 | public static final int[] zeroOneKnapsack(int[] values, int[] weights, int capacity) { 18 | if (weights.length != values.length) 19 | return null; 20 | 21 | int height = weights.length + 1; // weights==values 22 | int width = capacity + 1; 23 | int[][] output = new int[height][width]; 24 | for (int i = 1; i < height; i++) { 25 | int index = i - 1; 26 | for (int j = 1; j < width; j++) { 27 | if (i == 0 || j == 0) { 28 | output[i][j] = 0; 29 | } else { 30 | if (weights[index] > j) { 31 | output[i][j] = output[i - 1][j]; 32 | } else { 33 | int v = values[index] + output[i - 1][j - weights[index]]; 34 | output[i][j] = Math.max(output[i - 1][j], v); 35 | } 36 | } 37 | } 38 | } 39 | 40 | final List list = new ArrayList(); 41 | int i = height - 1; 42 | int j = width - 1; 43 | while (i != 0 && j != 0) { 44 | int current = output[i][j]; 45 | int above = output[i - 1][j]; 46 | if (current == above) { 47 | i -= 1; 48 | } else { 49 | i -= 1; 50 | j -= weights[i]; 51 | list.add(i); 52 | } 53 | } 54 | 55 | int count = 0; 56 | int[] result = new int[list.size()]; 57 | for (Object obj : list.toArray()) { 58 | if (obj instanceof Integer) 59 | result[count++] = (Integer) obj; 60 | } 61 | 62 | return result; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/LUDecomposition.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | import com.jwetherell.algorithms.data_structures.Matrix; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | /** 10 | * LU decomposition of matrix M produces 2 matrices L and U such that M = L*U 11 | * where L is lower triangular matrix and U is upper triangular matrix 12 | *

13 | * @see LU Decomposition (Wikipedia) 14 | *
15 | * @author Mateusz Cianciara 16 | * @author Justin Wetherell 17 | */ 18 | public class LUDecomposition { 19 | 20 | private int n = 0; 21 | private Double[][] L = null; 22 | private Double[][] A = null; 23 | private Integer[] permutation = null; 24 | 25 | public Matrix getL() { 26 | return new Matrix(n, n, L); 27 | } 28 | 29 | public Matrix getU() { 30 | return new Matrix(n, n, A); 31 | } 32 | 33 | public List getPermutation() { 34 | return new ArrayList(Arrays.asList(permutation)); 35 | } 36 | 37 | public LUDecomposition(Matrix input) { 38 | if (input.getCols() != input.getRows()) 39 | throw new IllegalArgumentException("Matrix is not square"); 40 | 41 | n = input.getCols(); 42 | L = new Double[n][n]; 43 | A = new Double[n][n]; 44 | permutation = new Integer[n]; 45 | 46 | for (int i = 0; i < n; i++) { 47 | for (int j = 0; j < n; j++) { 48 | L[i][j] = 0.0; 49 | A[i][j] = input.get(i, j); 50 | } 51 | } 52 | for (int i = 0; i < n; i++) { 53 | L[i][i] = 1.0; 54 | permutation[i] = i; 55 | } 56 | for (int row = 0; row < n; row++) { 57 | // find max in column 58 | int max_in_col = row; 59 | double curr_big = Math.abs(A[row][row]); 60 | for (int k = row + 1; k < n; k++) { 61 | if (curr_big < Math.abs(A[k][row])) { 62 | max_in_col = k; 63 | curr_big = Math.abs(A[k][row]); 64 | } 65 | } 66 | 67 | //swap rows 68 | if (row != max_in_col) { 69 | for (int i = 0; i < n; i++) { 70 | double temp = A[row][i]; 71 | A[row][i] = A[max_in_col][i]; 72 | A[max_in_col][i] = temp; 73 | 74 | if (i < row) { 75 | temp = L[row][i]; 76 | L[row][i] = L[max_in_col][i]; 77 | L[max_in_col][i] = temp; 78 | } 79 | } 80 | final int temp = permutation[row]; 81 | permutation[row] = permutation[max_in_col]; 82 | permutation[max_in_col] = temp; 83 | } 84 | 85 | //zero column number row 86 | final double p = A[row][row]; 87 | if (p == 0) 88 | return; 89 | 90 | for (int i = row + 1; i < n; i++) { 91 | final double y = A[i][row]; 92 | L[i][row] = y / p; 93 | 94 | for (int j = row; j < n; j++) { 95 | A[i][j] -= A[row][j] * (y / p); 96 | } 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/mathematics/RamerDouglasPeucker.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * The Ramer–Douglas–Peucker algorithm (RDP) is an algorithm for reducing the number of points in a 8 | * curve that is approximated by a series of points. 9 | *

10 | * @see Ramer–Douglas–Peucker Algorithm (Wikipedia) 11 | *
12 | * @author Justin Wetherell 13 | */ 14 | public class RamerDouglasPeucker { 15 | 16 | private RamerDouglasPeucker() { } 17 | 18 | private static final double sqr(double x) { 19 | return Math.pow(x, 2); 20 | } 21 | 22 | private static final double distanceBetweenPoints(double vx, double vy, double wx, double wy) { 23 | return sqr(vx - wx) + sqr(vy - wy); 24 | } 25 | 26 | private static final double distanceToSegmentSquared(double px, double py, double vx, double vy, double wx, double wy) { 27 | final double l2 = distanceBetweenPoints(vx, vy, wx, wy); 28 | if (l2 == 0) 29 | return distanceBetweenPoints(px, py, vx, vy); 30 | final double t = ((px - vx) * (wx - vx) + (py - vy) * (wy - vy)) / l2; 31 | if (t < 0) 32 | return distanceBetweenPoints(px, py, vx, vy); 33 | if (t > 1) 34 | return distanceBetweenPoints(px, py, wx, wy); 35 | return distanceBetweenPoints(px, py, (vx + t * (wx - vx)), (vy + t * (wy - vy))); 36 | } 37 | 38 | private static final double perpendicularDistance(double px, double py, double vx, double vy, double wx, double wy) { 39 | return Math.sqrt(distanceToSegmentSquared(px, py, vx, vy, wx, wy)); 40 | } 41 | 42 | private static final void douglasPeucker(List list, int s, int e, double epsilon, List resultList) { 43 | // Find the point with the maximum distance 44 | double dmax = 0; 45 | int index = 0; 46 | 47 | final int start = s; 48 | final int end = e-1; 49 | for (int i=start+1; i dmax) { 61 | index = i; 62 | dmax = d; 63 | } 64 | } 65 | // If max distance is greater than epsilon, recursively simplify 66 | if (dmax > epsilon) { 67 | // Recursive call 68 | douglasPeucker(list, s, index, epsilon, resultList); 69 | douglasPeucker(list, index, e, epsilon, resultList); 70 | } else { 71 | if ((end-start)>0) { 72 | resultList.add(list.get(start)); 73 | resultList.add(list.get(end)); 74 | } else { 75 | resultList.add(list.get(start)); 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * Given a curve composed of line segments find a similar curve with fewer points. 82 | * 83 | * @param list List of Double[] points (x,y) 84 | * @param epsilon Distance dimension 85 | * @return Similar curve with fewer points 86 | */ 87 | public static final List douglasPeucker(List list, double epsilon) { 88 | final List resultList = new ArrayList(); 89 | douglasPeucker(list, 0, list.size(), epsilon, resultList); 90 | return resultList; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/numbers/Complex.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.numbers; 2 | 3 | /** 4 | * A complex number is a number that can be expressed in the form a + bi, where a and b are real numbers and i is the 5 | * imaginary unit, satisfying the equation i2 = −1.[1] In this expression, a is the real part and b is the imaginary 6 | * part of the complex number. If z=a+bi z=a+bi, then Rz=a, Iz=b. 7 | *

8 | * @see Complex Number (Wikipedia) 9 | *
10 | * @author Mateusz Cianciara 11 | * @author Justin Wetherell 12 | */ 13 | public class Complex { 14 | 15 | public double real; 16 | public double imaginary; 17 | 18 | public Complex() { 19 | this.real = 0.0; 20 | this.imaginary = 0.0; 21 | } 22 | 23 | public Complex(double r, double i) { 24 | this.real = r; 25 | this.imaginary = i; 26 | } 27 | 28 | public Complex multiply(final Complex x) { 29 | final Complex copy = new Complex(this.real, this.imaginary); 30 | copy.real = this.real * x.real - this.imaginary * x.imaginary; 31 | copy.imaginary = this.imaginary * x.real + this.real * x.imaginary; 32 | return copy; 33 | } 34 | 35 | public Complex add(final Complex x) { 36 | final Complex copy = new Complex(this.real, this.imaginary); 37 | copy.real += x.real; 38 | copy.imaginary += x.imaginary; 39 | return copy; 40 | } 41 | 42 | public Complex sub(final Complex x) { 43 | final Complex copy = new Complex(this.real, this.imaginary); 44 | copy.real -= x.real; 45 | copy.imaginary -= x.imaginary; 46 | return copy; 47 | } 48 | 49 | public double abs() { 50 | return Math.sqrt(this.real * this.real + this.imaginary * this.imaginary); 51 | } 52 | 53 | public String toString() { 54 | return "(" + this.real + "," + this.imaginary + ")"; 55 | } 56 | 57 | public static Complex polar(final double rho, final double theta) { 58 | return (new Complex(rho * Math.cos(theta), rho * Math.sin(theta))); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/numbers/Longs.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.numbers; 2 | 3 | import java.math.BigDecimal; 4 | 5 | public class Longs { 6 | 7 | public static final String toBinaryUsingDivideAndModulus(long numberToConvert) { 8 | long longNumber = numberToConvert; 9 | if (longNumber<0) throw new IllegalArgumentException("Method argument cannot be negative. number="+longNumber); 10 | StringBuilder builder = new StringBuilder(); 11 | long temp = 0l; 12 | while (longNumber > 0) { 13 | temp = longNumber; 14 | longNumber = temp / 2; 15 | builder.append(temp % 2); 16 | } 17 | return builder.reverse().toString(); 18 | } 19 | 20 | public static final String toBinaryUsingShiftsAndModulus(long numberToConvert) { 21 | long longNumber = numberToConvert; 22 | if (longNumber<0) throw new IllegalArgumentException("Method argument cannot be negative. number="+longNumber); 23 | StringBuilder builder = new StringBuilder(); 24 | long temp = 0l; 25 | while (longNumber > 0) { 26 | temp = longNumber; 27 | longNumber = (temp >> 1); 28 | builder.append(temp % 2); 29 | } 30 | return builder.reverse().toString(); 31 | } 32 | 33 | public static final String toBinaryUsingBigDecimal(long numberToConvert) { 34 | long longNumber = numberToConvert; 35 | if (longNumber<0) throw new IllegalArgumentException("Method argument cannot be negative. number="+longNumber); 36 | StringBuilder builder = new StringBuilder(); 37 | BigDecimal zero = new BigDecimal(0); 38 | BigDecimal two = new BigDecimal(2); 39 | BigDecimal number = new BigDecimal(longNumber); 40 | BigDecimal[] decimals = null; 41 | while (number.compareTo(zero) > 0) { 42 | decimals = number.divideAndRemainder(two); 43 | number = decimals[0]; 44 | builder.append(decimals[1]); 45 | } 46 | return builder.reverse().toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/search/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.search; 2 | 3 | /** 4 | * In computer science, binary search, also known as half-interval search or logarithmic search, is a search algorithm that finds the position of a target value within a sorted array. Binary search 5 | * compares the target value to the middle element of the array; if they are unequal, the half in which the target cannot lie is eliminated and the search continues on the remaining half until it is 6 | * successful or the remaining half is empty. 7 | *

8 | * Worst-case performance O(log n)
9 | * Best-case performance O(1)
10 | * Average performance O(log n)
11 | * Worst-case space complexity O(1)
12 | *

13 | * @see Binary Search (Wikipedia) 14 | *
15 | * @author Justin Wetherell 16 | */ 17 | public class BinarySearch { 18 | 19 | private static final int SWITCH_TO_BRUTE_FORCE = 200; 20 | 21 | private static int[] sorted = null; 22 | 23 | // Assuming the array is sorted 24 | public static final int find(int value, int[] array, boolean optimize) { 25 | BinarySearch.sorted = array; 26 | try { 27 | return recursiveFind(value, 0, BinarySearch.sorted.length - 1, optimize); 28 | } finally { 29 | BinarySearch.sorted = null; 30 | } 31 | } 32 | //Recursively find the element 33 | //@return find the element value by recursively 34 | private static int recursiveFind(int value, int start, int end, boolean optimize) { 35 | if (start == end) { 36 | int lastValue = sorted[start]; // start==end 37 | if (value == lastValue) 38 | return start; // start==end 39 | return Integer.MAX_VALUE; 40 | } 41 | 42 | final int low = start; 43 | final int high = end + 1; // zero indexed, so add one. 44 | final int middle = low + ((high - low) / 2); 45 | 46 | final int middleValue = sorted[middle]; 47 | //checks if the middle index is element 48 | if (value == middleValue) 49 | return middle; 50 | //if value is greater than move to right 51 | if (value > middleValue) { 52 | if (optimize && (end - middle) <= SWITCH_TO_BRUTE_FORCE) 53 | return linearSearch(value, middle + 1, end); 54 | return recursiveFind(value, middle + 1, end, optimize); 55 | } 56 | if (optimize && (end - middle) <= SWITCH_TO_BRUTE_FORCE) 57 | return linearSearch(value, start, middle - 1); 58 | return recursiveFind(value, start, middle - 1, optimize); 59 | } 60 | //Linear search to find the element. 61 | //@value the element we want to find. 62 | //@start first index of the array in the array 63 | //@end last index of the array in the array. 64 | private static final int linearSearch(int value, int start, int end) { 65 | // From index i = start to i = end check if value matches sorted[i] 66 | for (int i = start; i <= end; i++) { 67 | int iValue = sorted[i]; 68 | if (value == iValue) 69 | return i; 70 | } 71 | return Integer.MAX_VALUE; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/search/InterpolationSearch.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.search; 2 | 3 | /** 4 | * Interpolation search is an algorithm for searching for a given key in an indexed array that has been ordered by numerical values assigned to the keys (key values). It parallels how humans search 5 | * through a telephone book for a particular name, the key value by which the book's entries are ordered. 6 | *

7 | * Worst-case performance O(n)
8 | * Average performance O(log(log(n)))
9 | *

10 | * @see Interpolation Search (Wikipedia) 11 | *
12 | * @author Justin Wetherell 13 | */ 14 | public class InterpolationSearch { 15 | 16 | private static int[] sorted = null; 17 | 18 | // Assuming the array is sorted 19 | public static final int find(int value, int[] array) { 20 | InterpolationSearch.sorted = array; 21 | try { 22 | return recursiveFind(value, 0, InterpolationSearch.sorted.length - 1); 23 | } finally { 24 | InterpolationSearch.sorted = null; 25 | } 26 | } 27 | 28 | private static int recursiveFind(int value, int start, int end) { 29 | if (start == end) { 30 | int lastValue = sorted[start]; // start==end 31 | if (value == lastValue) 32 | return start; // start==end 33 | return Integer.MAX_VALUE; 34 | } 35 | 36 | final int mid = start + ((value - sorted[start]) * (end - start)) / (sorted[end] - sorted[start]); 37 | if (mid < 0 || mid > end) 38 | return Integer.MAX_VALUE; 39 | int midValue = sorted[mid]; 40 | if (value == midValue) 41 | return mid; 42 | if (value > midValue) 43 | return recursiveFind(value, mid + 1, end); 44 | return recursiveFind(value, start, mid - 1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/search/LinearSearch.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.search; 2 | 3 | /** 4 | * In computer science, linear search or sequential search is a method for finding a target value within a list. It sequentially checks each element of the list for the target value until a match is 5 | * found or until all the elements have been searched. 6 | *

7 | * Worst-case performance O(n)
8 | * Best-case performance O(1)
9 | * Average performance O(n)
10 | * Worst-case space complexity O(1)
11 | *

12 | * @see Linear Search (Wikipedia) 13 | *
14 | * @author Justin Wetherell 15 | */ 16 | public class LinearSearch { 17 | 18 | public static final int find(int value, int[] array) { 19 | for (int i = 0; i < array.length; i++) { 20 | int iValue = array[i]; 21 | if (value == iValue) 22 | return i; 23 | } 24 | return Integer.MAX_VALUE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/search/LowerBound.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.search; 2 | 3 | /** 4 | * Lower bound search algorithm.
5 | * Lower bound is kind of binary search algorithm but:
6 | * -If searched element doesn't exist function returns index of first element which is bigger than searched value.
7 | * -If searched element is bigger than any array element function returns first index after last element.
8 | * -If searched element is lower than any array element function returns index of first element.
9 | * -If there are many values equals searched value function returns first occurrence.
10 | * Behaviour for unsorted arrays is unspecified. 11 | *

12 | * Complexity O(log n). 13 | *

14 | * @author Bartlomiej Drozd 15 | * @author Justin Wetherell 16 | */ 17 | public class LowerBound { 18 | 19 | private LowerBound() { } 20 | 21 | public static int lowerBound(int[] array, int length, int value) { 22 | int low = 0; 23 | int high = length; 24 | while (low < high) { 25 | final int mid = (low + high) / 2; 26 | //checks if the value is less than middle element of the array 27 | if (value <= array[mid]) { 28 | high = mid; 29 | } else { 30 | low = mid + 1; 31 | } 32 | } 33 | return low; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/search/QuickSelect.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.search; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * In computer science, quickselect is a selection algorithm to find the k-th smallest element in an unordered list. It is related to the quicksort sorting algorithm. 7 | *

8 | * Worst-case performance О(n2)
9 | * Best-case performance О(n)
10 | * Average performance O(n)
11 | *

12 | * @see Quickselect (Wikipedia) 13 | *
14 | * @author Justin Wetherell 15 | */ 16 | public class QuickSelect { 17 | 18 | private static final Random RANDOM = new Random(); 19 | 20 | private static int[] unsorted = null; 21 | private static int[] temp = null; 22 | 23 | public static final int find(int value, int[] array) { 24 | unsorted = array; 25 | temp = new int[unsorted.length]; 26 | try { 27 | int tempLength = unsorted.length; 28 | int length = tempLength; 29 | int pivot = unsorted[0]; 30 | while (length > 0) { 31 | length = tempLength; 32 | pivot = unsorted[RANDOM.nextInt(length)]; 33 | tempLength = 0; 34 | for (int i = 0; i < length; i++) { 35 | int iValue = unsorted[i]; 36 | if (value == iValue) 37 | return i; 38 | else if (value > pivot && iValue > pivot) 39 | temp[tempLength++] = iValue; 40 | else if (value < pivot && iValue < pivot) 41 | temp[tempLength++] = iValue; 42 | } 43 | unsorted = temp; 44 | length = tempLength; 45 | } 46 | return Integer.MAX_VALUE; 47 | } finally { 48 | QuickSelect.unsorted = null; 49 | QuickSelect.temp = null; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/search/UpperBound.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.search; 2 | 3 | /** 4 | * Upper bound search algorithm.
5 | * Upper bound is kind of binary search algorithm but:
6 | * -It returns index of first element which is grater than searched value.
7 | * -If searched element is bigger than any array element function returns first index after last element.
8 | *
9 | * Behaviour for unsorted arrays is unspecified. 10 | *

11 | * Complexity O(log n). 12 | *
13 | * @author Bartlomiej Drozd 14 | * @author Justin Wetherell 15 | */ 16 | public class UpperBound { 17 | 18 | private UpperBound() { } 19 | 20 | public static int upperBound(int[] array, int length, int value) { 21 | int low = 0; 22 | int high = length; 23 | while (low < high) { 24 | final int mid = (low + high) / 2; 25 | if (value >= array[mid]) { 26 | low = mid + 1; 27 | } else { 28 | high = mid; 29 | } 30 | } 31 | return low; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sequence/ArithmeticProgression.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sequence; 2 | 3 | /** 4 | * Compute the result of adding a sequence of numbers from N (startNumber) to N+X (startNumber+numberOfNumbersToCompute) 5 | *

6 | * @see Arithmetic Progression (Wikipedia) 7 | *
8 | * @author Justin Wetherell 9 | */ 10 | public class ArithmeticProgression { 11 | 12 | /** 13 | * Compute the result of adding X (numberOfNumbersToCompute) together starting at N (startNumber). 14 | *

15 | * e.g. result = N + (N+1) + (N+2) + (N+3) + ..... + (N+X) 16 | */ 17 | public static final long sequenceTotalUsingLoop(int startNumber, int numberOfNumbersToCompute) { 18 | int start = startNumber; 19 | int length = numberOfNumbersToCompute; 20 | long result = 0L; 21 | while (length > 0) { 22 | result += start++; 23 | length--; 24 | } 25 | return result; 26 | } 27 | 28 | /** 29 | * Compute the result of adding X (numberOfNumbersToCompute) together starting at N (startNumber) using triangular numbers. 30 | *

31 | * e.g. result = N + (N+1) + (N+2) + (N+3) + ..... + (N+X)
32 | *
33 | * @see Triangular Number (Wikipedia) 34 | */ 35 | public static final long sequenceTotalUsingTriangularNumbers(int startNumber, int numberOfNumbersToCompute) { 36 | // n*(n+1)/2 37 | final int start = startNumber; 38 | final int length = numberOfNumbersToCompute; 39 | 40 | long result = length * (length + 1) / 2; 41 | result += (start - 1) * length; 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sequence/LargestSumContiguousSubarray.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sequence; 2 | 3 | /** 4 | * Given an array of integers, we want to find the largest sum of contiguous 5 | * subarray. 6 | *

7 | * @see Maximum Subarray Problem (Wikipedia) 8 | *
9 | * @author Miguel Stephane KAKANAKOU 10 | * @author Justin Wetherell 11 | */ 12 | public class LargestSumContiguousSubarray { 13 | 14 | private LargestSumContiguousSubarray() { } 15 | 16 | /** 17 | * Largest sum of contiguous subarray using Kadane's algorithm. 18 | * 19 | * @param A 20 | * the given Array of integer 21 | * @return 22 | */ 23 | public static int getLargestSumContiguousSubarray(int[] A) { 24 | if (A == null) 25 | throw new NullPointerException("The given array is null"); 26 | 27 | int max_so_far = A[0]; 28 | int max_ending_here = A[0]; 29 | for (int i = 1; i < A.length; i++) { 30 | max_ending_here = Math.max(A[i], max_ending_here + A[i]); 31 | max_so_far = Math.max(max_so_far, max_ending_here); 32 | } 33 | return max_so_far; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sequence; 2 | 3 | /** 4 | * In computer science, the longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in 5 | * which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique. 6 | *

7 | * @see Longest Increasing Subsequence Problem (Wikipedia) 8 | *
9 | * @author Bartlomiej Drozd 10 | * @author Justin Wetherell 11 | */ 12 | public class LongestIncreasingSubsequence { 13 | 14 | private LongestIncreasingSubsequence() { } 15 | 16 | /** 17 | * Longest increasing subsequence solved using dynamic programming. 18 | */ 19 | public static int[] getLongestIncreasingSubsequence(int[] X) { 20 | final int[] P = new int[X.length]; 21 | final int[] M = new int[X.length+1]; 22 | int L = 0; 23 | for (int i=0; i L) { 43 | // If we found a subsequence longer than any we've found yet, update L 44 | L = newL; 45 | } 46 | } 47 | 48 | // Reconstruct the longest increasing subsequence 49 | final int[] S = new int[L]; 50 | int k = M[L]; 51 | for (int i=L-1; i>=0; i--) { 52 | S[i] = X[k]; 53 | k = P[k]; 54 | } 55 | 56 | return S; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sequence/LongestPalindromicSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sequence; 2 | 3 | /** 4 | * A longest palin­dromic sub­se­quence is a sequence that appears in the same 5 | * rel­a­tive order, but not nec­es­sar­ily contiguous(not sub­string) and 6 | * palin­drome in nature. 7 | *

8 | * Given a string, find the length of the longest palin­dromic sub­se­quence in it. 9 | *

10 | * @see Longest Palin­dromic Sub­se­quence (Wikipedia) 11 | *
12 | * @author Miguel Stephane KAKANAKOU 13 | * @author Justin Wetherell 14 | */ 15 | public class LongestPalindromicSubsequence { 16 | 17 | private LongestPalindromicSubsequence() { } 18 | 19 | /** 20 | * Find the length of the longest palin­dromic sub­se­quence in the given 21 | * string s using the dynamic programming approach. 22 | */ 23 | public static int getLongestPalindromeSubsequence(String s) { 24 | if (s == null) 25 | throw new NullPointerException("The given String is null"); 26 | 27 | final int len = s.length(); 28 | final int[][] M = new int[len][len]; 29 | final char[] ch = s.toCharArray(); 30 | 31 | initializeMatrix(M); 32 | fillMatrix(M, ch); 33 | return M[0][len-1]; 34 | } 35 | 36 | private static void initializeMatrix(int[][] M) { 37 | int len = M.length; 38 | for (int i=0; i 6 | * @see Substring occurs in String (GeeksForGeeks) 7 | *
8 | * @author Justin Wetherell 9 | */ 10 | public class SubsequenceCounter { 11 | 12 | private static char[] seq = null; 13 | private static char[] subseq = null; 14 | private static int[][] tbl = null; 15 | 16 | private SubsequenceCounter() { } 17 | 18 | /** 19 | * Finds the number of times a string occurs as a subsequence in a text. 20 | * 21 | * @param sequence Text to find subsequence in. 22 | * @param subSequence subsequence to find in the text. 23 | * @return Number of times a string occurs as a subsequence in a text 24 | */ 25 | public static int getCount(char[] sequence, char[] subSequence) { 26 | try { 27 | seq = sequence; 28 | subseq = subSequence; 29 | tbl = new int[seq.length + 1][subseq.length + 1]; 30 | 31 | for (int row = 0; row < tbl.length; row++) 32 | for (int col = 0; col < tbl[row].length; col++) 33 | tbl[row][col] = countMatches(row, col); 34 | 35 | return tbl[seq.length][subseq.length]; 36 | } finally { 37 | seq = null; 38 | subseq = null; 39 | tbl = null; 40 | } 41 | } 42 | 43 | private static int countMatches(int seqDigitsLeft, int subseqDigitsLeft) { 44 | if (subseqDigitsLeft == 0) 45 | return 1; 46 | 47 | if (seqDigitsLeft == 0) 48 | return 0; 49 | 50 | final char currSeqDigit = seq[seq.length - seqDigitsLeft]; 51 | final char currSubseqDigit = subseq[subseq.length - subseqDigitsLeft]; 52 | 53 | int result = 0; 54 | if (currSeqDigit == currSubseqDigit) 55 | result += tbl[seqDigitsLeft - 1][subseqDigitsLeft - 1]; 56 | result += tbl[seqDigitsLeft - 1][subseqDigitsLeft]; 57 | 58 | return result; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | /** 4 | * An American flag sort is an efficient, in-place variant of radix sort that 5 | * distributes items into hundreds of buckets. Non-comparative sorting 6 | * algorithms such as radix sort and American flag sort are typically used to 7 | * sort large objects such as strings, for which comparison is not a unit-time 8 | * operation. 9 | *

10 | * Family: Bucket.
11 | * Space: In-place.
12 | * Stable: False.
13 | *

14 | * Average case = O(n*k/d)
15 | * Worst case = O(n*k/d)
16 | * Best case = O(n*k/d)
17 | *

18 | * NOTE: n is the number of digits and k is the average bucket size 19 | *

20 | * @see American Flag Sort (Wikipedia) 21 | *
22 | * @author Justin Wetherell 23 | */ 24 | public class AmericanFlagSort { 25 | 26 | private static final int NUMBER_OF_BUCKETS = 10; // 10 for base 10 numbers 27 | 28 | private AmericanFlagSort() { } 29 | 30 | public static Integer[] sort(Integer[] unsorted) { 31 | int numberOfDigits = getMaxNumberOfDigits(unsorted); // Max number of digits 32 | int max = 1; 33 | for (int i = 0; i < numberOfDigits - 1; i++) 34 | max *= 10; 35 | sort(unsorted, 0, unsorted.length, max); 36 | return unsorted; 37 | } 38 | 39 | public static void sort(Integer[] unsorted, int start, int length, int divisor) { 40 | // First pass - find counts 41 | int[] count = new int[NUMBER_OF_BUCKETS]; 42 | int[] offset = new int[NUMBER_OF_BUCKETS]; 43 | int digit = 0; 44 | for (int i = start; i < length; i++) { 45 | int d = unsorted[i]; 46 | digit = getDigit(d, divisor); 47 | count[digit]++; 48 | } 49 | offset[0] = start + 0; 50 | for (int i = 1; i < NUMBER_OF_BUCKETS; i++) { 51 | offset[i] = count[i - 1] + offset[i - 1]; 52 | } 53 | // Second pass - move into position 54 | for (int b = 0; b < NUMBER_OF_BUCKETS; b++) { 55 | while (count[b] > 0) { 56 | int origin = offset[b]; 57 | int from = origin; 58 | int num = unsorted[from]; 59 | unsorted[from] = -1; 60 | do { 61 | digit = getDigit(num, divisor); 62 | int to = offset[digit]++; 63 | count[digit]--; 64 | int temp = unsorted[to]; 65 | unsorted[to] = num; 66 | num = temp; 67 | from = to; 68 | } while (from != origin); 69 | } 70 | } 71 | if (divisor > 1) { 72 | // Sort the buckets 73 | for (int i = 0; i < NUMBER_OF_BUCKETS; i++) { 74 | int begin = (i > 0) ? offset[i - 1] : start; 75 | int end = offset[i]; 76 | if (end - begin > 1) 77 | sort(unsorted, begin, end, divisor / 10); 78 | } 79 | } 80 | } 81 | 82 | private static int getMaxNumberOfDigits(Integer[] unsorted) { 83 | int max = Integer.MIN_VALUE; 84 | int temp = 0; 85 | for (int i : unsorted) { 86 | temp = (int) Math.log10(i) + 1; 87 | if (temp > max) 88 | max = temp; 89 | } 90 | return max; 91 | } 92 | 93 | private static int getDigit(int integer, int divisor) { 94 | return (integer / divisor) % 10; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | /** 4 | * Bubble sort is a simple sorting algorithm that works by repeatedly stepping 5 | * through the list to be sorted, comparing each pair of adjacent items and 6 | * swapping them if they are in the wrong order. The pass through the list is 7 | * repeated until no swaps are needed, which indicates that the list is sorted. 8 | *

9 | * Family: Exchanging.
10 | * Space: In-place.
11 | * Stable: True.
12 | *

13 | * Average case = O(n^2)
14 | * Worst case = O(n^2)
15 | * Best case = O(n)
16 | *

17 | * @see Bubble Sort (Wikipedia) 18 | *
19 | * @author Justin Wetherell 20 | */ 21 | public class BubbleSort> { 22 | 23 | private BubbleSort() { } 24 | //@param unsorted array 25 | //@return sorted array 26 | public static > T[] sort(T[] unsorted) { 27 | boolean swapped = true; 28 | int length = unsorted.length; 29 | while (swapped) { 30 | swapped = false; 31 | for (int i = 1; i < length; i++) { 32 | if (unsorted[i].compareTo(unsorted[i - 1]) < 0) { 33 | swap(i, i - 1, unsorted); 34 | swapped = true; 35 | } 36 | } 37 | length--; 38 | } 39 | return unsorted; 40 | } 41 | //swapping the value 42 | private static > void swap(int index1, int index2, T[] unsorted) { 43 | T value = unsorted[index1]; 44 | unsorted[index1] = unsorted[index2]; 45 | unsorted[index2] = value; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/CountingSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | /** 4 | * Counting sort is an algorithm for sorting a collection of objects according 5 | * to keys that are small integers; that is, it is an integer sorting algorithm. 6 | * It operates by counting the number of objects that have each distinct key 7 | * value, and using arithmetic on those counts to determine the positions of 8 | * each key value in the output sequence. 9 | *

10 | * Family: Counting.
11 | * Space: An Array of length r.
12 | * Stable: True.
13 | *

14 | * Average case = O(n+r)
15 | * Worst case = O(n+r)
16 | * Best case = O(n+r)
17 | *

18 | * NOTE: r is the range of numbers (0 to r) to be sorted. 19 | *

20 | * @see Counting Sort (Wikipedia) 21 | *
22 | * @author Justin Wetherell 23 | */ 24 | public class CountingSort { 25 | 26 | private CountingSort() { } 27 | 28 | public static Integer[] sort(Integer[] unsorted) { 29 | int maxValue = findMax(unsorted); 30 | int[] counts = new int[maxValue + 1];//counts number of elements 31 | updateCounts(unsorted, counts); 32 | populateCounts(unsorted, counts); 33 | return unsorted; 34 | } 35 | //finding maximum value in unsorted array 36 | private static int findMax(Integer[] unsorted) { 37 | int max = Integer.MIN_VALUE;//assume minimum value(-2147483648) of interger is maximum 38 | for (int i : unsorted) { 39 | if (i > max) 40 | max = i; 41 | } 42 | return max; 43 | } 44 | //Incrementing the number of counts in unsorted array 45 | private static void updateCounts(Integer[] unsorted, int[] counts) { 46 | for (int e : unsorted) 47 | counts[e]++; 48 | } 49 | 50 | private static void populateCounts(Integer[] unsorted, int[] counts) { 51 | int index = 0; 52 | for (int i = 0; i < counts.length; i++) { 53 | int e = counts[i]; 54 | while (e > 0) { 55 | unsorted[index++] = i; 56 | e--; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/HeapSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | /** 4 | * Heapsort is a comparison-based sorting algorithm to create a sorted array (or 5 | * list), and is part of the selection sort family. Although somewhat slower in 6 | * practice on most machines than a well-implemented quicksort, it has the 7 | * advantage of a more favorable worst-case O(n log n) runtime. 8 | *

9 | * Family: Selection.
10 | * Space: In-place.
11 | * Stable: False.
12 | *

13 | * Average case = O(n*log n)
14 | * Worst case = O(n*log n)
15 | * Best case = O(n*log n)
16 | *

17 | * @see Heap Sort (Wikipedia) 18 | *
19 | * @author Justin Wetherell 20 | */ 21 | public class HeapSort> { 22 | 23 | private HeapSort() { } 24 | 25 | public static > T[] sort(T[] unsorted) { 26 | createHeap(unsorted); 27 | sortHeap(unsorted); 28 | return unsorted; 29 | } 30 | 31 | private static > void sortHeap(T[] unsorted) { 32 | int length = unsorted.length; 33 | for (int index = length - 1; index > 0; index--) { 34 | swap(0, index, unsorted); // swap root with the last heap element 35 | int i = 0; // index of the element being moved down the tree 36 | while (true) { 37 | int left = (i * 2) + 1; 38 | if (left >= index) // node has no left child 39 | break; 40 | int right = left + 1; 41 | if (right >= index) { // node has a left child, but no right child 42 | if (unsorted[left].compareTo(unsorted[i]) > 0) 43 | swap(left, i, unsorted); // if left child is greater than node 44 | break; 45 | } 46 | T ithElement = unsorted[i]; 47 | T leftElement = unsorted[left]; 48 | T rightElement = unsorted[right]; 49 | if (ithElement.compareTo(leftElement) < 0) { // (left > i) 50 | if (unsorted[left].compareTo(rightElement) > 0) { // (left > right) 51 | swap(left, i, unsorted); 52 | i = left; 53 | continue; 54 | } 55 | // (left > i) 56 | swap(right, i, unsorted); 57 | i = right; 58 | continue; 59 | } 60 | // (i > left) 61 | if (rightElement.compareTo(ithElement) > 0) { 62 | swap(right, i, unsorted); 63 | i = right; 64 | continue; 65 | } 66 | // (n > left) & (n > right) 67 | break; 68 | } 69 | } 70 | } 71 | 72 | private static > void createHeap(T[] unsorted) { 73 | // Creates a max heap 74 | int size = 0; 75 | int length = unsorted.length; 76 | for (int i = 0; i < length; i++) { 77 | T e = unsorted[i]; 78 | size = add(size, e, unsorted); 79 | } 80 | } 81 | 82 | private static > int add(int size, T element, T[] unsorted) { 83 | int length = size; 84 | int i = length; 85 | unsorted[length++] = element; 86 | T e = unsorted[i]; 87 | int parentIndex = ((i - 1) / 2); 88 | T parent = unsorted[parentIndex]; 89 | while (e.compareTo(parent) > 0) { 90 | swap(parentIndex, i, unsorted); 91 | i = parentIndex; 92 | e = unsorted[i]; 93 | parentIndex = ((i - 1) / 2); 94 | parent = unsorted[parentIndex]; 95 | } 96 | return length; 97 | } 98 | 99 | private static > void swap(int parentIndex, int childIndex, T[] unsorted) { 100 | T parent = unsorted[parentIndex]; 101 | unsorted[parentIndex] = unsorted[childIndex]; 102 | unsorted[childIndex] = parent; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | /** 4 | * Insertion sort is a simple sorting algorithm: a comparison sort in which the 5 | * sorted array (or list) is built one entry at a time. It is much less 6 | * efficient on large lists than more advanced algorithms such as quicksort, 7 | * heapsort, or merge sort. 8 | *

9 | * Family: Insertion.
10 | * Space: In-place.
11 | * Stable: True.
12 | *

13 | * Average case = O(n^2)
14 | * Worst case = O(n^2)
15 | * Best case = O(n)
16 | *

17 | * @see Insertion Sort (Wikipedia) 18 | *
19 | * @author Justin Wetherell 20 | */ 21 | public class InsertionSort> { 22 | 23 | private InsertionSort() { } 24 | 25 | public static > T[] sort(T[] unsorted) { 26 | int length = unsorted.length; 27 | for (int i = 1; i < length; i++) { 28 | sort(i, unsorted); 29 | } 30 | return unsorted; 31 | } 32 | 33 | private static > void sort(int i, T[] unsorted) { 34 | for (int j = i; j > 0; j--) { 35 | T jthElement = unsorted[j]; 36 | T jMinusOneElement = unsorted[j - 1]; 37 | if (jthElement.compareTo(jMinusOneElement) < 0) { 38 | unsorted[j - 1] = jthElement; 39 | unsorted[j] = jMinusOneElement; 40 | } else { 41 | break; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/MergeSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | /** 4 | * Merge sort is an O(n log n) comparison-based sorting algorithm. Most 5 | * implementations produce a stable sort, which means that the implementation 6 | * preserves the input order of equal elements in the sorted output. 7 | *

8 | * Family: Merging.
9 | * Space: In-place.
10 | * Stable: True.
11 | *

12 | * Average case = O(n*log n)
13 | * Worst case = O(n*log n)
14 | * Best case = O(n*log n)
15 | *

16 | * @see Merge Sort (Wikipedia) 17 | *
18 | * @author Justin Wetherell 19 | */ 20 | @SuppressWarnings("unchecked") 21 | public class MergeSort> { 22 | 23 | public static enum SPACE_TYPE { IN_PLACE, NOT_IN_PLACE } 24 | 25 | private MergeSort() { } 26 | 27 | public static > T[] sort(SPACE_TYPE type, T[] unsorted) { 28 | sort(type, 0, unsorted.length, unsorted); 29 | return unsorted; 30 | } 31 | 32 | private static > void sort(SPACE_TYPE type, int start, int length, T[] unsorted) { 33 | if (length > 2) { 34 | int aLength = (int) Math.floor(length / 2); 35 | int bLength = length - aLength; 36 | sort(type, start, aLength, unsorted); 37 | sort(type, start + aLength, bLength, unsorted); 38 | if (type == SPACE_TYPE.IN_PLACE) 39 | mergeInPlace(start, aLength, start + aLength, bLength, unsorted); 40 | else 41 | mergeWithExtraStorage(start, aLength, start + aLength, bLength, unsorted); 42 | } else if (length == 2) { 43 | T e = unsorted[start + 1]; 44 | if (e.compareTo(unsorted[start]) < 0) { 45 | unsorted[start + 1] = unsorted[start]; 46 | unsorted[start] = e; 47 | } 48 | } 49 | } 50 | 51 | private static > void mergeInPlace(int aStart, int aLength, int bStart, int bLength, T[] unsorted) { 52 | int i = aStart; 53 | int j = bStart; 54 | int aSize = aStart + aLength; 55 | int bSize = bStart + bLength; 56 | while (i < aSize && j < bSize) { 57 | T a = unsorted[i]; 58 | T b = unsorted[j]; 59 | if (b.compareTo(a) < 0) { 60 | // Shift everything to the right one spot 61 | System.arraycopy(unsorted, i, unsorted, i+1, j-i); 62 | unsorted[i] = b; 63 | i++; 64 | j++; 65 | aSize++; 66 | } else { 67 | i++; 68 | } 69 | } 70 | } 71 | 72 | private static > void mergeWithExtraStorage(int aStart, int aLength, int bStart, int bLength, T[] unsorted) { 73 | int count = 0; 74 | T[] output = (T[]) new Comparable[aLength + bLength]; 75 | int i = aStart; 76 | int j = bStart; 77 | int aSize = aStart + aLength; 78 | int bSize = bStart + bLength; 79 | while (i < aSize || j < bSize) { 80 | T a = null; 81 | if (i < aSize) { 82 | a = unsorted[i]; 83 | } 84 | T b = null; 85 | if (j < bSize) { 86 | b = unsorted[j]; 87 | } 88 | if (a != null && b == null) { 89 | output[count++] = a; 90 | i++; 91 | } else if (b != null && a == null) { 92 | output[count++] = b; 93 | j++; 94 | } else if (b != null && b.compareTo(a) <= 0) { 95 | output[count++] = b; 96 | j++; 97 | } else { 98 | output[count++] = a; 99 | i++; 100 | } 101 | } 102 | int x = 0; 103 | int size = aStart + aLength + bLength; 104 | for (int y = aStart; y < size; y++) { 105 | unsorted[y] = output[x++]; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/QuickSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Quicksort is a sorting algorithm which, on average, makes O(n*log n) comparisons to sort 7 | * n items. In the worst case, it makes O(n^2) comparisons, though this behavior is 8 | * rare. Quicksort is often faster in practice than other algorithms. 9 | *

10 | * Family: Divide and conquer.
11 | * Space: In-place.
12 | * Stable: False.
13 | *

14 | * Average case = O(n*log n)
15 | * Worst case = O(n^2)
16 | * Best case = O(n) [three-way partition and equal keys]
17 | *

18 | * @see Quicksort (Wikipedia) 19 | *
20 | * @author Justin Wetherell 21 | */ 22 | public class QuickSort> { 23 | 24 | private static final Random RAND = new Random(); 25 | 26 | public static enum PIVOT_TYPE { 27 | FIRST, MIDDLE, RANDOM 28 | } 29 | 30 | public static PIVOT_TYPE type = PIVOT_TYPE.RANDOM; 31 | 32 | private QuickSort() { } 33 | 34 | public static > T[] sort(PIVOT_TYPE pivotType, T[] unsorted) { 35 | int pivot = 0; 36 | if (pivotType == PIVOT_TYPE.MIDDLE) { 37 | pivot = unsorted.length/2; 38 | } else if (pivotType == PIVOT_TYPE.RANDOM) { 39 | pivot = getRandom(unsorted.length); 40 | } 41 | sort(pivot, 0, unsorted.length - 1, unsorted); 42 | return unsorted; 43 | } 44 | 45 | private static > void sort(int index, int start, int finish, T[] unsorted) { 46 | int pivotIndex = start + index; 47 | T pivot = unsorted[pivotIndex]; 48 | int s = start; 49 | int f = finish; 50 | while (s <= f) { 51 | while (unsorted[s].compareTo(pivot) < 0) 52 | s++; 53 | while (unsorted[f].compareTo(pivot) > 0) 54 | f--; 55 | if (s <= f) { 56 | swap(s, f, unsorted); 57 | s++; 58 | f--; 59 | } 60 | } 61 | if (start < f) { 62 | pivotIndex = getRandom((f - start) + 1); 63 | sort(pivotIndex, start, f, unsorted); 64 | } 65 | if (s < finish) { 66 | pivotIndex = getRandom((finish - s) + 1); 67 | sort(pivotIndex, s, finish, unsorted); 68 | } 69 | } 70 | 71 | private static final int getRandom(int length) { 72 | if (type == PIVOT_TYPE.RANDOM && length > 0) 73 | return RAND.nextInt(length); 74 | if (type == PIVOT_TYPE.FIRST && length > 0) 75 | return 0; 76 | return length / 2; 77 | } 78 | 79 | private static > void swap(int index1, int index2, T[] unsorted) { 80 | T index2Element = unsorted[index1]; 81 | unsorted[index1] = unsorted[index2]; 82 | unsorted[index2] = index2Element; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/RadixSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Radix sort is a non-comparative integer sorting algorithm that sorts data 7 | * with integer keys by grouping keys by the individual digits which share the 8 | * same significant position and value. A positional notation is required, but 9 | * because integers can represent strings of characters (e.g., names or dates) 10 | * and specially formatted floating point numbers, radix sort is not limited to 11 | * integers. 12 | *

13 | * Family: Bucket.
14 | * Space: 10 Buckets with at most n integers per bucket.
15 | * Stable: True.
16 | *

17 | * Average case = O(n*k)
18 | * Worst case = O(n*k)
19 | * Best case = O(n*k)
20 | *

21 | * NOTE: n is the number of digits and k is the average bucket size 22 | *

23 | * @see Radix Sort (Wikipedia) 24 | *
25 | * @author Justin Wetherell 26 | */ 27 | public class RadixSort { 28 | 29 | private static final int NUMBER_OF_BUCKETS = 10; // 10 for base 10 numbers 30 | 31 | private RadixSort() { } 32 | 33 | public static Integer[] sort(Integer[] unsorted) { 34 | int[][] buckets = new int[NUMBER_OF_BUCKETS][10]; 35 | for (int i = 0; i < NUMBER_OF_BUCKETS; i++) 36 | buckets[i][0] = 1; // Size is one since the size is stored in first element 37 | int numberOfDigits = getMaxNumberOfDigits(unsorted); // Max number of digits 38 | int divisor = 1; 39 | for (int n = 0; n < numberOfDigits; n++) { 40 | int digit = 0; 41 | for (int d : unsorted) { 42 | digit = getDigit(d, divisor); 43 | buckets[digit] = add(d, buckets[digit]); 44 | } 45 | int index = 0; 46 | for (int i = 0; i < NUMBER_OF_BUCKETS; i++) { 47 | int[] bucket = buckets[i]; 48 | int size = bucket[0]; 49 | for (int j = 1; j < size; j++) { 50 | unsorted[index++] = bucket[j]; 51 | } 52 | buckets[i][0] = 1; // reset the size 53 | } 54 | divisor *= 10; 55 | } 56 | return unsorted; 57 | } 58 | 59 | private static int getMaxNumberOfDigits(Integer[] unsorted) { 60 | int max = Integer.MIN_VALUE; 61 | int temp = 0; 62 | for (int i : unsorted) { 63 | temp = (int) Math.log10(i) + 1; 64 | if (temp > max) 65 | max = temp; 66 | } 67 | return max; 68 | } 69 | 70 | private static int getDigit(int integer, int divisor) { 71 | return (integer / divisor) % 10; 72 | } 73 | 74 | private static int[] add(int integer, int[] bucket) { 75 | int size = bucket[0]; // size is stored in first element 76 | int length = bucket.length; 77 | int[] result = bucket; 78 | if (size >= length) { 79 | result = Arrays.copyOf(result, ((length * 3) / 2) + 1); 80 | } 81 | result[size] = integer; 82 | result[0] = ++size; 83 | return result; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/sorts/ShellSort.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sorts; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Shellsort, also known as Shell sort or Shell's method, is an in-place 8 | * comparison sort. It generalizes an exchanging sort, such as insertion or 9 | * bubble sort, by starting the comparison and exchange of elements with 10 | * elements that are far apart before finishing with neighboring elements. 11 | * Starting with far apart elements can move some out-of-place elements into 12 | * position faster than a simple nearest neighbor exchange. 13 | *

14 | * Family: Exchanging.
15 | * Space: In-place.
16 | * Stable: False.
17 | *

18 | * Average case = depends on the gap
19 | * Worst case = O(n * log^2 n)
20 | * Best case = O(n)
21 | *

22 | * @see Shell Sort (Wikipedia) 23 | *
24 | * @author Justin Wetherell 25 | */ 26 | public class ShellSort> { 27 | 28 | private ShellSort() { } 29 | 30 | public static > T[] sort(int[] shells, T[] unsorted) { 31 | for (int gap : shells) { 32 | // Allocate arrays 33 | List> subarrays = new ArrayList>(gap); 34 | for (int i = 0; i < gap; i++) { 35 | subarrays.add(new ArrayList(10)); 36 | } 37 | // Populate sub-arrays 38 | int i = 0; 39 | int length = unsorted.length; 40 | while (i < length) { 41 | for (int j = 0; j < gap; j++) { 42 | if (i >= length) 43 | continue; 44 | T v = unsorted[i++]; 45 | List list = subarrays.get(j); 46 | list.add(v); 47 | } 48 | } 49 | // Sort all sub-arrays 50 | sortSubarrays(subarrays); 51 | // Push the sub-arrays into the int array 52 | int k = 0; 53 | int iter = 0; 54 | while (k < length) { 55 | for (int j = 0; j < gap; j++) { 56 | if (k >= length) 57 | continue; 58 | unsorted[k++] = subarrays.get(j).get(iter); 59 | } 60 | iter++; 61 | } 62 | } 63 | return unsorted; 64 | } 65 | 66 | private static > void sortSubarrays(List> lists) { 67 | for (List list : lists) { 68 | sort(list); 69 | } 70 | } 71 | 72 | /** 73 | * Insertion sort 74 | * 75 | * @param list 76 | * List to be sorted. 77 | */ 78 | private static > void sort(List list) { 79 | int size = list.size(); 80 | for (int i = 1; i < size; i++) { 81 | for (int j = i; j > 0; j--) { 82 | T a = list.get(j); 83 | T b = list.get(j - 1); 84 | if (a.compareTo(b) < 0) { 85 | list.set(j - 1, a); 86 | list.set(j, b); 87 | } else { 88 | break; 89 | } 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.strings; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * This class implements KMP algorithm for finding length of maximal prefix-suffix for each prefix of the string. 8 | * Prefix-suffix of string S is a substring which occurs at the beginning and at the end of S. 9 | *

10 | * Time complexity: O(n)
11 | *

12 | * @see Knuth Morris Pratt (Wikipedia) 13 | *
14 | * @author Szymon Stankiewicz 15 | * @author Justin Wetherell 16 | */ 17 | public class KnuthMorrisPratt { 18 | 19 | private KnuthMorrisPratt() {} 20 | 21 | /** 22 | * This function implements KMP algorithm for finding length of maximal prefix-suffix for each prefix of the string. 23 | * Prefix-suffix of string S is a substring which occurs at the beginning and at the end of S. 24 | *

25 | * @param text Text 26 | * @return maximal length of prefix-suffix for each prefix of the string text 27 | */ 28 | public static List getPrefSufTable(String text) { 29 | 30 | final List prefSufTable = new ArrayList(); 31 | final char[] chars = text.toCharArray(); 32 | 33 | if (text.length() == 0) 34 | return prefSufTable; 35 | 36 | prefSufTable.add(0); 37 | 38 | for (int i = 1; i 0 && (chars[i] != chars[sizeOfPrefSuf])) 41 | sizeOfPrefSuf = prefSufTable.get(sizeOfPrefSuf-1); // because string is 0-indexed 42 | 43 | // if characters at this positions are different then sizeOfPrefSuf is equal to zero, 44 | // so there is no proper prefix-suffix 45 | if (chars[i] == chars[sizeOfPrefSuf]) { 46 | prefSufTable.add(sizeOfPrefSuf+1); 47 | } else { 48 | prefSufTable.add(0); 49 | } 50 | } 51 | return prefSufTable; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/strings/Manacher.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.strings; 2 | 3 | /** 4 | * The longest palindromic substring or longest symmetric factor problem 5 | * is the problem of finding a maximum-length contiguous substring of a given string that is also a palindrome. 6 | *

7 | * The longest palindromic substring problem should not be confused with 8 | * the different problem of finding the longest palindromic subsequence. 9 | *

10 | * Manacher's algorithm finds the longest palindromic substring in linear time O(n); where n = length(input) 11 | *

12 | * @see Manacher's Algorithm (Wikipedia) 13 | *
14 | * @author Piotr Kruk 15 | * @author Justin Wetherell 16 | */ 17 | public class Manacher { 18 | 19 | private Manacher() {} 20 | 21 | /** 22 | * This function implements Manacher's algorithm that finds 23 | * the longest palindromic substring in a linear time 24 | * If there is no unique longest palindromic substring it returns the first one to occur 25 | * 26 | * @param input 27 | * @return the longest palindromic substring in input 28 | */ 29 | public static String getLongestPalindromicSubstring(String input) { 30 | if (input == null) 31 | return null; 32 | 33 | final int length = input.length(); 34 | if (length == 0) 35 | return ""; 36 | 37 | // arr represents input string in a way that will act the same for strings of even and uneven length 38 | // i.e. '#' is placed between each letter from input 39 | final char[] arr = new char[2 * length + 1]; 40 | for (int i = length - 1; i >= 0; i--) { 41 | arr[2 * i + 1] = input.charAt(i); 42 | arr[2 * i] = '#'; 43 | } 44 | arr[2 * length] = '#'; 45 | 46 | final int arrLength = length * 2; 47 | 48 | // LPS[i] - palindrome span(radius) with center at arr[i] 49 | final int[] LPS = new int[arrLength + 1]; 50 | int p = 0; 51 | for (int i = 1; i <= arrLength; i++) { 52 | LPS[i] = 0; 53 | if (LPS[p] + p >= i) 54 | LPS[i] = Math.min(LPS[2 * p - i], p + LPS[p] - i); 55 | while (i + LPS[i] + 1 <= arrLength && i - LPS[i] - 1 >= 0 && arr[i + LPS[i] + 1] == arr[i - LPS[i] - 1]) 56 | LPS[i]++; 57 | if (p + LPS[p] < i + LPS[i]) 58 | p = i; 59 | } 60 | 61 | // find the palindrome with the biggest span 62 | int valueMax = 0; 63 | int indexMax = 0; 64 | for (int i = 0; i < arrLength; i++) { 65 | if (valueMax < LPS[i]) { 66 | valueMax = LPS[i]; 67 | indexMax = i; 68 | } 69 | } 70 | 71 | // reconstruct the palindrome given its index in LPS and span 72 | final int palindromeSpan = valueMax / 2; 73 | if (indexMax % 2 == 0) { 74 | return input.substring(indexMax/2 - palindromeSpan, indexMax/2 + palindromeSpan); 75 | } else { 76 | return input.substring(indexMax/2 - palindromeSpan, indexMax/2 + palindromeSpan + 1); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/jwetherell/algorithms/strings/Rotation.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.strings; 2 | 3 | /** 4 | * Rotation of the string is some cyclic transformation of that string. 5 | * More formally a string s = uv is said to be a rotation of t if t = vu. 6 | *

7 | * @see String Rotation (Wikipedia) 8 | *
9 | * @Author Szymon Stankiewicz 10 | * @author Justin Wetherell 11 | */ 12 | public class Rotation { 13 | 14 | private static char charAt(String text, int pos) { 15 | pos = pos % text.length(); 16 | return text.charAt(pos); 17 | } 18 | 19 | private static int compare(char a, char b, boolean greater) { 20 | if (a == b) 21 | return 0; 22 | return (a < b) ^ greater ? -1 : 1; 23 | } 24 | 25 | private static String bestRotation(String text, boolean greatest) { 26 | if (text.length() < 2) 27 | return text; 28 | 29 | final int n = text.length() * 2; 30 | int k = 0; 31 | int i = 0, j = 1; 32 | while (i + k < n && j + k < n) { 33 | final char a = charAt(text, i+k); 34 | final char b = charAt(text, j+k); 35 | final int comp = compare(a, b, greatest); 36 | if (comp == 0) { 37 | k++; 38 | } else if (comp > 0) { 39 | i += k+1; 40 | if (i <= j ) 41 | i = j + 1; 42 | k = 0; 43 | } else { 44 | j += k+1; 45 | if (j <= i) 46 | j = i + 1; 47 | k = 0; 48 | } 49 | } 50 | final int pos = i < j ? i : j; 51 | return text.substring(pos) + text.substring(0, pos); 52 | } 53 | 54 | /** 55 | * Finds lexicographically minimal string rotation. 56 | * Lexicographically minimal string rotation is a rotation of a string possessing the 57 | * lowest lexicographical order of all such rotations. 58 | * Finding the lexicographically minimal rotation is useful as a way of normalizing strings. 59 | *

60 | * @see Lexicographically Minimal String Rotation (Wikipedia) 61 | *

62 | * This function implements Duval's algorithm. 63 | *

64 | * @see Duval's Algorithm (Wikipedia) 65 | *

66 | * Complexity: O(n) 67 | *
68 | * @param text 69 | * @return lexicographicall minimal rotation of text 70 | */ 71 | public static String getLexicographicallyMinimalRotation(String text) { 72 | return bestRotation(text, false); 73 | } 74 | 75 | /** 76 | * Finds lexicographically maximal string rotation. 77 | * Lexicographically maximal string rotation is a rotation of a string possessing the 78 | * highest lexicographical order of all such rotations. 79 | * Finding the lexicographically maximal rotation is useful as a way of normalizing strings. 80 | *

81 | * @see Lexicographically Minimal String Rotation (Wikipedia) 82 | *

83 | * This function implements Duval's algorithm. 84 | * @see Duval's Algorithm (Wikipedia) 85 | *

86 | * Complexity: O(n) 87 | *
88 | * @param text 89 | * @return lexicographicall minimal rotation of text 90 | */ 91 | public static String getLexicographicallyMaximalRotation(String text) { 92 | return bestRotation(text, true); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/AVLTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.AVLTree; 10 | import com.jwetherell.algorithms.data_structures.BinarySearchTree; 11 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 14 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 15 | 16 | public class AVLTreeTests { 17 | 18 | @Test 19 | public void testAVLTree() { 20 | TestData data = Utils.generateTestData(1000); 21 | 22 | String bstName = "AVL Tree"; 23 | BinarySearchTree bst = new AVLTree(); 24 | Collection bstCollection = bst.toCollection(); 25 | 26 | assertTrue(TreeTest.testTree(bst, Integer.class, bstName, 27 | data.unsorted, data.invalid)); 28 | assertTrue(JavaCollectionTest.testCollection(bstCollection, Integer.class, bstName, 29 | data.unsorted, data.sorted, data.invalid)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/AllTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import org.junit.runner.JUnitCore; 4 | import org.junit.runner.RunWith; 5 | import org.junit.runners.Suite; 6 | import org.junit.runners.Suite.SuiteClasses; 7 | 8 | @RunWith(Suite.class) 9 | @SuiteClasses( { 10 | AVLTreeTests.class, 11 | BinaryHeapTests.class, 12 | BinarySearchTreeTests.class, 13 | BTreeTests.class, 14 | CompactSuffixTrieTests.class, 15 | DisjointSetTests.class, 16 | FenwickTreeTests.class, 17 | GraphTests.class, 18 | HashArrayMappedTreeTests.class, 19 | HashMapTests.class, 20 | ImplicitKeyTreapTests.class, 21 | IntervalTreeTests.class, 22 | KdTreeTests.class, 23 | ListTests.class, 24 | MatrixTests.class, 25 | PatriciaTreeTests.class, 26 | QuadTreeTests.class, 27 | QueueTests.class, 28 | RadixTrieTests.class, 29 | RedBlackTreeTests.class, 30 | SegmentTreeTests.class, 31 | SkipListMapTests.class, 32 | SkipListTests.class, 33 | SplayTreeTests.class, 34 | StackTests.class, 35 | SuffixTreeTests.class, 36 | SuffixTrieTests.class, 37 | TreapTests.class, 38 | TreeMapTests.class, 39 | TrieTests.class, 40 | TrieMapTests.class 41 | } 42 | ) 43 | 44 | public class AllTests { 45 | 46 | /** 47 | * @param args 48 | */ 49 | public static void main(String[] args) { 50 | JUnitCore core = new JUnitCore(); 51 | core.run(AllTests.class); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/BTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.BTree; 10 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 14 | 15 | public class BTreeTests { 16 | 17 | @Test 18 | public void testBTree() { 19 | TestData data = Utils.generateTestData(1000); 20 | 21 | String bstName = "B-Tree"; 22 | BTree bst = new BTree(2); 23 | Collection bstCollection = bst.toCollection(); 24 | 25 | assertTrue(TreeTest.testTree(bst, Integer.class, bstName, data.unsorted, data.invalid)); 26 | assertTrue(JavaCollectionTest.testCollection(bstCollection, Integer.class, bstName, 27 | data.unsorted, data.sorted, data.invalid)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/CompactSuffixTrieTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | import com.jwetherell.algorithms.data_structures.CompactSuffixTrie; 9 | 10 | public class CompactSuffixTrieTests { 11 | 12 | @Test 13 | public void testCompactSuffixTrie() { 14 | String bookkeeper = "bookkeeper"; 15 | CompactSuffixTrie trie = new CompactSuffixTrie(bookkeeper); 16 | 17 | boolean exists = trie.doesSubStringExist(bookkeeper); 18 | assertTrue("YIKES!! " + bookkeeper + " doesn't exists.", exists); 19 | 20 | String failed = "booker"; 21 | exists = trie.doesSubStringExist(failed); 22 | assertFalse("YIKES!! " + failed + " exists.", exists); 23 | 24 | String pass = "kkee"; 25 | exists = trie.doesSubStringExist(pass); 26 | assertTrue("YIKES!! " + pass + " doesn't exists.", exists); 27 | } 28 | 29 | @Test 30 | public void testCompactSuffixTrie_equals() { 31 | String bookkeeper = "bookkeeper"; 32 | CompactSuffixTrie trie = new CompactSuffixTrie(bookkeeper); 33 | 34 | String bookkeeper_1 = "bookkeeper"; 35 | CompactSuffixTrie trie_1 = new CompactSuffixTrie(bookkeeper_1); 36 | 37 | boolean equal = trie.equals(trie_1); 38 | assertTrue("YIKES!! " + bookkeeper + " and " + bookkeeper_1 + " are not equal.", equal); 39 | 40 | 41 | String failed = "failed"; 42 | trie = new CompactSuffixTrie(failed); 43 | 44 | String failed_1 = "failet"; 45 | trie_1 = new CompactSuffixTrie(failed_1); 46 | 47 | equal = trie.equals(trie_1); 48 | assertFalse("YIKES!! " + failed + " and " + failed_1 + " are equal.", equal); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/HashArrayMappedTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import com.jwetherell.algorithms.data_structures.HashArrayMappedTrie; 8 | import com.jwetherell.algorithms.data_structures.test.common.JavaMapTest; 9 | import com.jwetherell.algorithms.data_structures.test.common.MapTest; 10 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 11 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 12 | 13 | public class HashArrayMappedTreeTests { 14 | 15 | @Test 16 | public void testHAMT() { 17 | TestData data = Utils.generateTestData(1000); 18 | 19 | String mapName = "HAMT"; 20 | HashArrayMappedTrie map = new HashArrayMappedTrie(); 21 | java.util.Map jMap = map.toMap(); 22 | 23 | assertTrue(MapTest.testMap(map, Integer.class, mapName, 24 | data.unsorted, data.invalid)); 25 | assertTrue(JavaMapTest.testJavaMap(jMap, Integer.class, mapName, 26 | data.unsorted, data.sorted, data.invalid)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/HashMapTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import com.jwetherell.algorithms.data_structures.HashMap; 8 | import com.jwetherell.algorithms.data_structures.test.common.JavaMapTest; 9 | import com.jwetherell.algorithms.data_structures.test.common.MapTest; 10 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 11 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 12 | 13 | public class HashMapTests { 14 | 15 | @Test 16 | public void testHashMap() { 17 | TestData data = Utils.generateTestData(1000); 18 | 19 | String mapName = "ProbingHashMap"; 20 | HashMap map = new HashMap(HashMap.Type.PROBING); 21 | java.util.Map jMap = map.toMap(); 22 | 23 | assertTrue(MapTest.testMap(map, Integer.class, mapName, data.unsorted, data.invalid)); 24 | assertTrue(JavaMapTest.testJavaMap(jMap, Integer.class, mapName, data.unsorted, data.sorted, data.invalid)); 25 | 26 | mapName = "LinkingHashMap"; 27 | map = new HashMap(HashMap.Type.CHAINING); 28 | jMap = map.toMap(); 29 | 30 | assertTrue(MapTest.testMap(map, Integer.class, mapName, data.unsorted, data.invalid)); 31 | assertTrue(JavaMapTest.testJavaMap(jMap, Integer.class, mapName, data.unsorted, data.sorted, data.invalid)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/IntervalSumTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Random; 9 | 10 | import org.junit.Test; 11 | 12 | import com.jwetherell.algorithms.data_structures.IntervalSum; 13 | 14 | public class IntervalSumTest { 15 | 16 | @Test 17 | public void properSumAllElementsTest() { 18 | final IntervalSum sub = new IntervalSum(); 19 | for (int i = 0; i<=100; i++) 20 | sub.add(i); 21 | for (int i = 0; i<=100; i++) 22 | assertEquals(i*(i+1)/2, sub.sum(i)); 23 | assertEquals(100*101/2, sub.sum()); 24 | } 25 | 26 | @Test 27 | public void randomGeneratedTest() { 28 | final Random generator = new Random(42); 29 | final List list = new ArrayList(); 30 | for (int i = 0; i<=100; i++) 31 | list.add(i); 32 | final IntervalSum sum = new IntervalSum(list); 33 | for (int i = 0; i<1000000; i++) { 34 | final int pos = generator.nextInt(100); 35 | final int val = generator.nextInt(2000000) - 1000000; 36 | sum.set(pos, val); 37 | list.set(pos, val); 38 | assertEquals(val, sum.get(pos)); 39 | } 40 | 41 | int s = 0; 42 | final List prefSum = new ArrayList(); 43 | prefSum.add(s); 44 | for (Integer val: list) { 45 | s += val; 46 | prefSum.add(s); 47 | } 48 | 49 | for (int i = 0; i<100; i++) { 50 | for (int j = i; j<100; j++) { 51 | assertEquals(prefSum.get(j+1) - prefSum.get(i), sum.sum(i, j)); 52 | } 53 | } 54 | } 55 | 56 | @Test 57 | public void setIndexOutOfRangeTest() { 58 | final IntervalSum sum = new IntervalSum(100); 59 | boolean thrown = false; 60 | try { 61 | sum.set(101, 10); 62 | } catch (IndexOutOfBoundsException e) { 63 | thrown = true; 64 | } 65 | assertTrue(thrown); 66 | } 67 | 68 | @Test 69 | public void sumIndexOutOfRangeTest() { 70 | final IntervalSum sum = new IntervalSum(100); 71 | boolean thrown = false; 72 | try { 73 | sum.sum(101); 74 | } catch (IndexOutOfBoundsException e) { 75 | thrown = true; 76 | } 77 | assertTrue(thrown); 78 | } 79 | 80 | @Test 81 | public void endBeforeStartTest() { 82 | final IntervalSum sum = new IntervalSum(100); 83 | boolean thrown = false; 84 | try { 85 | sum.sum(101, 100); 86 | } catch (IllegalArgumentException e) { 87 | thrown = true; 88 | } 89 | assertTrue(thrown); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/KdTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | import org.junit.Test; 10 | 11 | import com.jwetherell.algorithms.data_structures.KdTree; 12 | import com.jwetherell.algorithms.data_structures.KdTree.XYZPoint; 13 | 14 | public class KdTreeTests { 15 | 16 | @Test 17 | public void testKdTree() { 18 | List points = new ArrayList(); 19 | XYZPoint p1 = new XYZPoint(2, 3); 20 | points.add(p1); 21 | XYZPoint p2 = new XYZPoint(5, 4); 22 | points.add(p2); 23 | XYZPoint p3 = new XYZPoint(9, 6); 24 | points.add(p3); 25 | XYZPoint p4 = new XYZPoint(4, 7); 26 | points.add(p4); 27 | XYZPoint p5 = new XYZPoint(8, 1); 28 | points.add(p5); 29 | XYZPoint p6 = new XYZPoint(7, 2); 30 | points.add(p6); 31 | KdTree kdTree = new KdTree(points); 32 | 33 | Collection result = kdTree.nearestNeighbourSearch(1, p3); 34 | assertTrue("K-D Tree query error. query=(k=1, p=(9, 6)) returned="+result, result.contains(p3)); 35 | 36 | XYZPoint search = new XYZPoint(1, 4); 37 | result = kdTree.nearestNeighbourSearch(4, search); 38 | assertTrue("K-D Tree query error. query=(k=4, p=(1, 4)) returned="+result, (result.contains(p1) && 39 | result.contains(p2) && 40 | result.contains(p4) && 41 | result.contains(p6)) 42 | ); 43 | 44 | kdTree.remove(p6); 45 | kdTree.remove(p4); 46 | kdTree.remove(p3); 47 | kdTree.remove(p5); 48 | kdTree.remove(p1); 49 | kdTree.remove(p2); 50 | } 51 | 52 | @Test 53 | public void testKdTree_as_iterable() { 54 | List points = new ArrayList(); 55 | XYZPoint p1 = new XYZPoint(2, 3); 56 | points.add(p1); 57 | XYZPoint p2 = new XYZPoint(5, 4); 58 | points.add(p2); 59 | XYZPoint p3 = new XYZPoint(9, 6); 60 | points.add(p3); 61 | XYZPoint p4 = new XYZPoint(4, 7); 62 | points.add(p4); 63 | XYZPoint p5 = new XYZPoint(8, 1); 64 | points.add(p5); 65 | XYZPoint p6 = new XYZPoint(7, 2); 66 | points.add(p6); 67 | KdTree kdTree = new KdTree(points); 68 | 69 | for (final XYZPoint p : kdTree) 70 | assertTrue(kdTree.contains(p)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import com.jwetherell.algorithms.data_structures.LCPArray; 4 | import org.junit.Test; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | 9 | import static org.junit.Assert.*; 10 | 11 | public class LCPArrayTest { 12 | 13 | @Test 14 | public void smallTest(){ 15 | String string = "asdasdd"; 16 | LCPArray LCPArrayBuilder = new LCPArray(string); 17 | ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); 18 | ArrayList result = new ArrayList(); 19 | 20 | result.addAll(Arrays.asList(null, 0, 3, 0, 1, 1, 0, 2)); 21 | 22 | assertEquals(LCPArray, result); 23 | } 24 | 25 | @Test 26 | public void longTest(){ 27 | String string = "aasfaasdsadasdfasdasdasdasfdasfassdfas"; 28 | LCPArray LCPArrayBuilder = new LCPArray(string); 29 | ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); 30 | ArrayList result = new ArrayList(); 31 | 32 | result.addAll(Arrays.asList(null, 0, 3, 1, 1, 2, 8, 5, 3, 3, 2, 4, 3, 2, 0, 33 | 6, 4, 3, 4, 1, 4, 1, 0, 2, 3, 3, 1, 0, 1, 1, 7, 4, 2, 5, 2, 1, 3, 2, 1)); 34 | 35 | assertEquals(LCPArray, result); 36 | } 37 | 38 | @Test 39 | public void singleLetterTest(){ 40 | String string = "aaaaaaaaaaaa"; 41 | LCPArray LCPArrayBuilder = new LCPArray(string); 42 | ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); 43 | ArrayList result = new ArrayList(); 44 | 45 | result.addAll(Arrays.asList(null , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); 46 | 47 | assertEquals(LCPArray, result); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertFalse; 5 | import static org.junit.Assert.assertNull; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | import org.junit.Test; 9 | 10 | import com.jwetherell.algorithms.data_structures.LowestCommonAncestor; 11 | import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.NodesNotInSameTreeException; 12 | import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.TreeNode; 13 | 14 | public class LowestCommonAncestorTest { 15 | 16 | @Test 17 | public void largeTreeTest() throws NodesNotInSameTreeException { 18 | 19 | final TreeNode root = new TreeNode(); 20 | final TreeNode left = root.addChild(); 21 | final TreeNode middle = root.addChild(); 22 | final TreeNode right = root.addChild(); 23 | 24 | //long path 25 | TreeNode v = left; 26 | for (int i = 0; i<1000; i++) 27 | v = v.addChild(); 28 | TreeNode leftRight = left.addChild(); 29 | assertEquals(LowestCommonAncestor.lowestCommonAncestor(v, leftRight), left); 30 | 31 | for (int i = 0; i<2000; i++) { 32 | leftRight = leftRight.addChild(); 33 | assertEquals(LowestCommonAncestor.lowestCommonAncestor(v, leftRight), left); 34 | } 35 | 36 | assertEquals(LowestCommonAncestor.lowestCommonAncestor(middle, right), root); 37 | assertEquals(LowestCommonAncestor.lowestCommonAncestor(root, right), root); 38 | assertEquals(LowestCommonAncestor.lowestCommonAncestor(root, root), root); 39 | 40 | final TreeNode root2 = new TreeNode(); 41 | boolean thrownException = false; 42 | try { 43 | LowestCommonAncestor.lowestCommonAncestor(v, root2); 44 | } catch (NodesNotInSameTreeException e) { 45 | thrownException = true; 46 | } 47 | assertTrue(thrownException); 48 | 49 | final TreeNode deepChild = v.addChild(101); 50 | assertEquals(deepChild, root.find(101)); 51 | assertTrue(root.contains(101)); 52 | 53 | assertNull(root.find(102)); 54 | assertFalse(root.contains(102)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/PatriciaTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.PatriciaTrie; 10 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 14 | 15 | public class PatriciaTreeTests { 16 | 17 | @Test 18 | public void testPatriciaTrie() { 19 | TestData data = Utils.generateTestData(1000); 20 | 21 | String bstName = "PatriciaTrie"; 22 | PatriciaTrie bst = new PatriciaTrie(); 23 | Collection bstCollection = bst.toCollection(); 24 | 25 | assertTrue(TreeTest.testTree(bst, String.class, bstName, 26 | data.unsorted, data.invalid)); 27 | assertTrue(JavaCollectionTest.testCollection(bstCollection, String.class, bstName, 28 | data.unsorted, data.sorted, data.invalid)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/QueueTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | import java.util.Iterator; 7 | 8 | import org.junit.Test; 9 | 10 | import com.jwetherell.algorithms.data_structures.Queue; 11 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.QueueTest; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 14 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 15 | 16 | public class QueueTests { 17 | 18 | @Test 19 | public void testArrayQueue() { 20 | TestData data = Utils.generateTestData(2500); 21 | 22 | String aName = "Queue [array]"; 23 | Queue.ArrayQueue aQueue = new Queue.ArrayQueue(); 24 | Collection aCollection = aQueue.toCollection(); 25 | 26 | assertTrue(QueueTest.testQueue(aQueue, aName, 27 | data.unsorted, data.invalid)); 28 | assertTrue(JavaCollectionTest.testCollection(aCollection, Integer.class, aName, 29 | data.unsorted, data.sorted, data.invalid)); 30 | 31 | // Specific test based on bug 32 | aQueue = new Queue.ArrayQueue(); 33 | for (int i = 0; i < 1024; i++) { 34 | aQueue.offer(i); 35 | } 36 | aQueue.poll(); 37 | aQueue.offer(1024); 38 | Iterator it = aQueue.toQueue().iterator(); 39 | while (it.hasNext()) 40 | it.next(); 41 | } 42 | 43 | @Test 44 | public void testLinkedQueue() { 45 | TestData data = Utils.generateTestData(250); 46 | 47 | String lName = "Queue [linked]"; 48 | Queue.LinkedQueue lQueue = new Queue.LinkedQueue(); 49 | Collection lCollection = lQueue.toCollection(); 50 | 51 | assertTrue(QueueTest.testQueue(lQueue, lName, 52 | data.unsorted, data.invalid)); 53 | assertTrue(JavaCollectionTest.testCollection(lCollection, Integer.class, lName, 54 | data.unsorted, data.sorted, data.invalid)); 55 | 56 | lQueue = new Queue.LinkedQueue(); 57 | for (int i = 0; i < 1024; i++) { 58 | lQueue.offer(i); 59 | } 60 | lQueue.poll(); 61 | lQueue.offer(1024); 62 | Iterator it = lQueue.toQueue().iterator(); 63 | while (it.hasNext()) 64 | it.next(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/RadixTrieTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | import junit.framework.Assert; 5 | 6 | import org.junit.Test; 7 | 8 | import com.jwetherell.algorithms.data_structures.RadixTrie; 9 | import com.jwetherell.algorithms.data_structures.test.common.JavaMapTest; 10 | import com.jwetherell.algorithms.data_structures.test.common.MapTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 13 | 14 | public class RadixTrieTests { 15 | 16 | @Test 17 | public void testRadixTrie() { 18 | TestData data = Utils.generateTestData(1000); 19 | runTests(data); 20 | } 21 | 22 | /** This was an error condition previously in converting a black node with children into a white terminating node **/ 23 | @Test 24 | public void cornerCase() { 25 | RadixTrie map = new RadixTrie(); 26 | map.put("1", 1); 27 | map.put("112", 112); 28 | map.put("113", 1123); 29 | map.put("11", 11); 30 | map.remove("11"); 31 | Integer r = map.put("11", 11); 32 | Assert.assertTrue(r==null); 33 | } 34 | 35 | private void runTests(TestData data) { 36 | String mapName = "RadixTrie"; 37 | RadixTrie map = new RadixTrie(); 38 | java.util.Map jMap = map.toMap(); 39 | 40 | assertTrue(MapTest.testMap(map, String.class, mapName, 41 | data.unsorted, data.invalid)); 42 | assertTrue(JavaMapTest.testJavaMap(jMap, String.class, mapName, 43 | data.unsorted, data.sorted, data.invalid)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/RedBlackTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.RedBlackTree; 10 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 14 | 15 | public class RedBlackTreeTests { 16 | 17 | @Test 18 | public void testRedBlackTree() { 19 | TestData data = Utils.generateTestData(1000); 20 | 21 | String bstName = "Red-Black Tree"; 22 | RedBlackTree bst = new RedBlackTree(); 23 | Collection bstCollection = bst.toCollection(); 24 | 25 | assertTrue(TreeTest.testTree(bst, Integer.class, bstName, 26 | data.unsorted, data.invalid)); 27 | assertTrue(JavaCollectionTest.testCollection(bstCollection, Integer.class, bstName, 28 | data.unsorted, data.sorted, data.invalid)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/SkipListMapTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import com.jwetherell.algorithms.data_structures.SkipListMap; 8 | import com.jwetherell.algorithms.data_structures.test.common.JavaMapTest; 9 | import com.jwetherell.algorithms.data_structures.test.common.MapTest; 10 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 11 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 12 | 13 | public class SkipListMapTests { 14 | 15 | @Test 16 | public void testSkipListMap() { 17 | TestData data = Utils.generateTestData(1000); 18 | 19 | String mapName = "SkipListMap"; 20 | SkipListMap map = new SkipListMap(); 21 | java.util.Map jMap = map.toMap(); 22 | 23 | assertTrue(MapTest.testMap(map, String.class, mapName, 24 | data.unsorted, data.invalid)); 25 | assertTrue(JavaMapTest.testJavaMap(jMap, Integer.class, mapName, 26 | data.unsorted, data.sorted, data.invalid)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/SkipListTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.SkipList; 10 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.SetTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 14 | 15 | public class SkipListTests { 16 | 17 | @Test 18 | public void testSkipList() { 19 | TestData data = Utils.generateTestData(1000); 20 | 21 | String sName = "SkipList"; 22 | SkipList sList = new SkipList(); 23 | Collection lCollection = sList.toCollection(); 24 | 25 | assertTrue(SetTest.testSet(sList, sName, 26 | data.unsorted, data.invalid)); 27 | assertTrue(JavaCollectionTest.testCollection(lCollection, Integer.class, sName, 28 | data.unsorted, data.sorted, data.invalid)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/SplayTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.BinarySearchTree; 10 | import com.jwetherell.algorithms.data_structures.SplayTree; 11 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 14 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 15 | 16 | public class SplayTreeTests { 17 | 18 | @Test 19 | public void testSplayTree() { 20 | TestData data = Utils.generateTestData(1000); 21 | 22 | String bstName = "Splay Tree"; 23 | BinarySearchTree bst = new SplayTree(); 24 | Collection bstCollection = bst.toCollection(); 25 | 26 | assertTrue(TreeTest.testTree(bst, Integer.class, bstName, 27 | data.unsorted, data.invalid)); 28 | assertTrue(JavaCollectionTest.testCollection(bstCollection, Integer.class, bstName, 29 | data.unsorted, data.sorted, data.invalid)); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/StackTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.Stack; 10 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.StackTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 14 | 15 | public class StackTests { 16 | 17 | @Test 18 | public void testArrayStack() { 19 | TestData data = Utils.generateTestData(1000); 20 | 21 | String aName = "Stack [array]"; 22 | Stack.ArrayStack aStack = new Stack.ArrayStack(); 23 | Collection aCollection = aStack.toCollection(); 24 | 25 | assertTrue(StackTest.testStack(aStack, aName, 26 | data.unsorted, data.invalid)); 27 | assertTrue(JavaCollectionTest.testCollection(aCollection, Integer.class, aName, 28 | data.unsorted, data.sorted, data.invalid)); 29 | } 30 | 31 | @Test 32 | public void testLinkedStack() { 33 | TestData data = Utils.generateTestData(1000); 34 | 35 | String lName = "Stack [linked]"; 36 | Stack.LinkedStack lStack = new Stack.LinkedStack(); 37 | Collection lCollection = lStack.toCollection(); 38 | 39 | assertTrue(StackTest.testStack(lStack, lName, 40 | data.unsorted, data.invalid)); 41 | assertTrue(JavaCollectionTest.testCollection(lCollection, Integer.class, lName, 42 | data.unsorted, data.sorted, data.invalid)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/SuffixArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import com.jwetherell.algorithms.data_structures.SuffixArray; 4 | import com.jwetherell.algorithms.data_structures.SuffixTree; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Set; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | public class SuffixArrayTest { 13 | 14 | @Test 15 | public void testSuffixArray(){ 16 | String string = "aasfaasdsadasdfasdasdasdasfdasfassdfas"; 17 | 18 | SuffixArray suffixArrayBuilder = new SuffixArray(string); 19 | SuffixTree suffixTree = new SuffixTree(string); 20 | 21 | Set suffixSet = suffixTree.getSuffixes(); 22 | ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); 23 | 24 | int i=0; 25 | for(String suffix : suffixSet){ 26 | String substring = string.substring(suffixArray.get(i++)); 27 | assertTrue(suffix.equals(substring)); 28 | } 29 | } 30 | 31 | @Test 32 | public void testKMRarray(){ 33 | String string = "aasfaasdsadasdfasdasdasdasfdasfassdfas"; 34 | 35 | SuffixArray suffixArrayBuilder = new SuffixArray(string); 36 | ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); 37 | ArrayList KMRarray = suffixArrayBuilder.getKMRarray(); 38 | 39 | int length = string.length(); 40 | for(int i=0; i tree = new SuffixTree(bookkeeper); 16 | assertTrue(SuffixTreeTest.suffixTreeTest(tree, bookkeeper)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/SuffixTrieTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import com.jwetherell.algorithms.data_structures.SuffixTrie; 8 | import com.jwetherell.algorithms.data_structures.test.common.SuffixTreeTest; 9 | 10 | public class SuffixTrieTests { 11 | 12 | @Test 13 | public void testSuffixTrie() { 14 | String bookkeeper = "bookkeeper"; 15 | SuffixTrie trie = new SuffixTrie(bookkeeper); 16 | assertTrue(SuffixTreeTest.suffixTreeTest(trie, bookkeeper)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | import junit.framework.Assert; 10 | 11 | import org.junit.Test; 12 | 13 | import com.jwetherell.algorithms.data_structures.TernarySearchTree; 14 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 15 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 16 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 17 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 18 | 19 | public class TernarySearchTreeTests { 20 | 21 | @Test 22 | public void test1() { 23 | final List tests = new ArrayList(); 24 | tests.add("BEE"); 25 | tests.add("BEEN"); 26 | tests.add("BEAST"); 27 | tests.add("BELOW"); 28 | tests.add("BEFORE"); 29 | tests.add("BUT"); 30 | tests.add("CAT"); 31 | tests.add("BE"); 32 | tests.add("B"); 33 | tests.add("DAD"); 34 | tests.add("APPLE"); 35 | 36 | final TernarySearchTree bst = new TernarySearchTree(); 37 | 38 | // Add 39 | bst.add(null); 40 | bst.add(""); 41 | for (String s : tests) 42 | bst.add(s); 43 | bst.add(null); 44 | bst.add(""); 45 | Assert.assertFalse(bst.add("BE")); 46 | 47 | // contains 48 | Assert.assertFalse(bst.contains(null)); 49 | Assert.assertFalse(bst.contains("")); 50 | for (String s : tests) 51 | Assert.assertTrue(bst.contains(s)); 52 | Assert.assertFalse(bst.contains(null)); 53 | Assert.assertFalse(bst.contains("")); 54 | 55 | // remove 56 | Assert.assertTrue(bst.remove(null)==null); 57 | Assert.assertTrue(bst.remove("")==null); 58 | for (String s : tests) 59 | Assert.assertTrue(bst.remove(s)!=null); 60 | Assert.assertTrue(bst.remove(null)==null); 61 | Assert.assertTrue(bst.remove("")==null); 62 | } 63 | 64 | @Test 65 | public void testTernary() { 66 | TestData data = Utils.generateTestData(1000); 67 | 68 | String bstName = "TernarySearchTreeTests"; 69 | TernarySearchTree bst = new TernarySearchTree(); 70 | Collection bstCollection = bst.toCollection(); 71 | 72 | assertTrue(TreeTest.testTree(bst, String.class, bstName, 73 | data.unsorted, data.invalid)); 74 | assertTrue(JavaCollectionTest.testCollection(bstCollection, String.class, bstName, 75 | data.unsorted, data.sorted, data.invalid)); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/TreapTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.BinarySearchTree; 10 | import com.jwetherell.algorithms.data_structures.Treap; 11 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 14 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 15 | 16 | public class TreapTests { 17 | 18 | @Test 19 | public void testTreap() { 20 | TestData data = Utils.generateTestData(1000); 21 | 22 | String bstName = "Treap"; 23 | BinarySearchTree bst = new Treap(); 24 | Collection bstCollection = bst.toCollection(); 25 | 26 | assertTrue(TreeTest.testTree(bst, Integer.class, bstName, 27 | data.unsorted, data.invalid)); 28 | assertTrue(JavaCollectionTest.testCollection(bstCollection, Integer.class, bstName, 29 | data.unsorted, data.sorted, data.invalid)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/TreeMapTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import com.jwetherell.algorithms.data_structures.TreeMap; 8 | import com.jwetherell.algorithms.data_structures.test.common.JavaMapTest; 9 | import com.jwetherell.algorithms.data_structures.test.common.MapTest; 10 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 11 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 12 | 13 | public class TreeMapTests { 14 | 15 | @Test 16 | public void testTreeMap() { 17 | TestData data = Utils.generateTestData(1000); 18 | 19 | String mapName = "TreeMap"; 20 | TreeMap map = new TreeMap(); 21 | java.util.Map jMap = map.toMap(); 22 | 23 | assertTrue(MapTest.testMap(map, String.class, mapName, 24 | data.unsorted, data.invalid)); 25 | assertTrue(JavaMapTest.testJavaMap(jMap, Integer.class, mapName, 26 | data.unsorted, data.sorted, data.invalid)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/TrieMapTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | import com.jwetherell.algorithms.data_structures.TrieMap; 8 | import com.jwetherell.algorithms.data_structures.test.common.JavaMapTest; 9 | import com.jwetherell.algorithms.data_structures.test.common.MapTest; 10 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 11 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 12 | 13 | public class TrieMapTests { 14 | 15 | @Test 16 | public void testTrieMap() { 17 | TestData data = Utils.generateTestData(1000); 18 | 19 | String mapName = "TrieMap"; 20 | TrieMap map = new TrieMap(); 21 | java.util.Map jMap = map.toMap(); 22 | 23 | assertTrue(MapTest.testMap(map, String.class, mapName, 24 | data.unsorted, data.invalid)); 25 | assertTrue(JavaMapTest.testJavaMap(jMap, String.class, mapName, 26 | data.unsorted, data.sorted, data.invalid)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/TrieTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import java.util.Collection; 6 | 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.data_structures.Trie; 10 | import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; 11 | import com.jwetherell.algorithms.data_structures.test.common.TreeTest; 12 | import com.jwetherell.algorithms.data_structures.test.common.Utils; 13 | import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; 14 | 15 | public class TrieTests { 16 | 17 | @Test 18 | public void testTrie() { 19 | TestData data = Utils.generateTestData(1000); 20 | 21 | String bstName = "Trie"; 22 | Trie bst = new Trie(); 23 | Collection bstCollection = bst.toCollection(); 24 | 25 | assertTrue(TreeTest.testTree(bst, String.class, bstName, 26 | data.unsorted, data.invalid)); 27 | assertTrue(JavaCollectionTest.testCollection(bstCollection, String.class, bstName, 28 | data.unsorted, data.sorted, data.invalid)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/common/IteratorTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test.common; 2 | 3 | import java.util.Iterator; 4 | 5 | public class IteratorTest { 6 | 7 | public static > boolean testIterator(Iterator iter) { 8 | while (iter.hasNext()) { 9 | T item = iter.next(); 10 | if (item==null) { 11 | System.err.println("Iterator failure."); 12 | return false; 13 | } 14 | } 15 | return true; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/common/ListIteratorTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test.common; 2 | 3 | import java.util.ListIterator; 4 | import java.util.NoSuchElementException; 5 | 6 | public class ListIteratorTest { 7 | 8 | public static > boolean testListIterator(ListIterator iter, Class type, 9 | Integer[] data, int size) { 10 | // Make sure you catch going prev at the start 11 | boolean exceptionThrown = false; 12 | try { 13 | iter.previous(); 14 | } catch (NoSuchElementException e) { 15 | exceptionThrown = true; 16 | } 17 | if (!exceptionThrown) { 18 | System.err.println("ListIterator exception failure."); 19 | return false; 20 | } 21 | 22 | for (int i = 0; i < data.length; i++) { 23 | Integer value = data[i]; 24 | T item = Utils.parseT(value, type); 25 | iter.add(item); 26 | } 27 | while (iter.hasPrevious()) 28 | iter.previous(); 29 | 30 | int i = 0; 31 | while (iter.hasNext()) { 32 | T item = iter.next(); 33 | int idx = iter.nextIndex(); 34 | if (idx!=++i) { 35 | System.err.println("ListIterator index failure."); 36 | return false; 37 | } 38 | if (item==null) { 39 | System.err.println("ListIterator item is null."); 40 | return false; 41 | } 42 | } 43 | 44 | // We should be at the end of the collection, this should fail 45 | exceptionThrown = false; 46 | try { 47 | iter.next(); 48 | } catch (NoSuchElementException e) { 49 | exceptionThrown = true; 50 | } 51 | if (!exceptionThrown) { 52 | System.err.println("ListIterator exception failure."); 53 | return false; 54 | } 55 | 56 | //This should be list.size 57 | iter.nextIndex(); 58 | int listSize = iter.nextIndex(); 59 | if (listSize!=size) { 60 | System.err.println("ListIterator ARRAY_SIZE failure."); 61 | return false; 62 | } 63 | 64 | i--; 65 | while (iter.hasPrevious()) { 66 | T item = iter.previous(); 67 | int idx = iter.previousIndex(); 68 | if (idx!=--i) { 69 | System.err.println("ListIterator index failure."); 70 | return false; 71 | } 72 | if (item==null) { 73 | System.err.println("ListIterator item is null."); 74 | return false; 75 | } 76 | } 77 | 78 | // We should be at the beginning of the collection, this should fail 79 | exceptionThrown = false; 80 | try { 81 | iter.previous(); 82 | } catch (NoSuchElementException e) { 83 | exceptionThrown = true; 84 | } 85 | if (!exceptionThrown) { 86 | System.err.println("ListIterator exception failure."); 87 | return false; 88 | } 89 | 90 | // This should be negative one 91 | iter.previousIndex(); 92 | int negOne = iter.previousIndex(); 93 | if (negOne!=-1) { 94 | System.err.println("ListIterator negative_one failure."); 95 | return false; 96 | } 97 | 98 | // Remove all using iterator 99 | while (iter.hasNext()) { 100 | iter.next(); 101 | iter.remove(); 102 | } 103 | 104 | return true; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/data_structures/test/common/SuffixTreeTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.data_structures.test.common; 2 | 3 | import com.jwetherell.algorithms.data_structures.interfaces.ISuffixTree; 4 | 5 | public class SuffixTreeTest { 6 | 7 | /** 8 | * In computer science, a suffix tree (also called PAT tree or, in an earlier 9 | * form, position tree) is a compressed trie containing all the suffixes of 10 | * the given text as their keys and positions in the text as their values. 11 | * Suffix trees allow particularly fast implementations of many important 12 | * string operations. 13 | * 14 | * @param tree Suffix tree to test. 15 | * @param test String to use in testing the suffix tree. 16 | * @return True if the suffix tree passes it's invariants tests. 17 | */ 18 | public static boolean suffixTreeTest(ISuffixTree tree, String test) { 19 | boolean exists = tree.doesSubStringExist(test); 20 | if (!exists) { 21 | System.err.println("YIKES!! " + test + " doesn't exists."); 22 | Utils.handleError(test,tree); 23 | return false; 24 | } 25 | 26 | String failed = test+"Z"; 27 | exists = tree.doesSubStringExist(failed); 28 | if (exists) { 29 | System.err.println("YIKES!! " + failed + " exists."); 30 | Utils.handleError(failed,tree); 31 | return false; 32 | } 33 | 34 | String pass = test.substring(0, 6); 35 | exists = tree.doesSubStringExist(pass); 36 | if (!exists) { 37 | System.err.println("YIKES!! " + pass + " doesn't exists."); 38 | Utils.handleError(pass,tree); 39 | return false; 40 | } 41 | 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/graph/test/BreadthFirstTraversalTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import junit.framework.Assert; 7 | 8 | import org.junit.Test; 9 | 10 | import com.jwetherell.algorithms.data_structures.Graph; 11 | import com.jwetherell.algorithms.graph.BreadthFirstTraversal; 12 | 13 | public class BreadthFirstTraversalTest { 14 | 15 | private static final byte[][] adjacencyMatrix = new byte[4][4]; 16 | static { 17 | // v0 18 | adjacencyMatrix[0][1] = 1; 19 | adjacencyMatrix[0][2] = 1; 20 | // v1 21 | adjacencyMatrix[1][2] = 1; 22 | // v2 23 | adjacencyMatrix[2][0] = 1; 24 | adjacencyMatrix[2][3] = 1; 25 | // v3 26 | adjacencyMatrix[3][3] = 1; 27 | } 28 | 29 | @Test 30 | public void test0() { 31 | final int[] result = BreadthFirstTraversal.breadthFirstTraversal(4, adjacencyMatrix, 2); 32 | Assert.assertTrue(result[0]==2); 33 | Assert.assertTrue(result[1]==0); 34 | Assert.assertTrue(result[2]==3); 35 | Assert.assertTrue(result[3]==1); 36 | } 37 | 38 | @Test 39 | public void test1() { 40 | final int[] result = BreadthFirstTraversal.breadthFirstTraversal(4, adjacencyMatrix, 0); 41 | Assert.assertTrue(result[0]==0); 42 | Assert.assertTrue(result[1]==1); 43 | Assert.assertTrue(result[2]==2); 44 | Assert.assertTrue(result[3]==3); 45 | } 46 | 47 | private static final List> vertices = new ArrayList>(); 48 | private static final List> edges = new ArrayList>(); 49 | 50 | private static final Graph.Vertex v0 = new Graph.Vertex(0); 51 | private static final Graph.Vertex v1 = new Graph.Vertex(1); 52 | private static final Graph.Vertex v2 = new Graph.Vertex(2); 53 | private static final Graph.Vertex v3 = new Graph.Vertex(3); 54 | 55 | static { 56 | vertices.add(v0); 57 | vertices.add(v1); 58 | vertices.add(v2); 59 | vertices.add(v3); 60 | 61 | edges.add(new Graph.Edge(0, v0, v1)); 62 | edges.add(new Graph.Edge(0, v0, v2)); 63 | edges.add(new Graph.Edge(0, v1, v2)); 64 | edges.add(new Graph.Edge(0, v2, v0)); 65 | edges.add(new Graph.Edge(0, v2, v3)); 66 | edges.add(new Graph.Edge(0, v3, v3)); 67 | } 68 | 69 | private static final Graph graph = new Graph(Graph.TYPE.DIRECTED, vertices, edges); 70 | 71 | @Test 72 | public void test2() { 73 | final Graph.Vertex[] result = BreadthFirstTraversal.breadthFirstTraversal(graph, v2); 74 | Assert.assertTrue(result[0].getValue()==2); 75 | Assert.assertTrue(result[1].getValue()==0); 76 | Assert.assertTrue(result[2].getValue()==3); 77 | Assert.assertTrue(result[3].getValue()==1); 78 | } 79 | 80 | @Test 81 | public void test3() { 82 | final Graph.Vertex[] result = BreadthFirstTraversal.breadthFirstTraversal(graph, v0); 83 | Assert.assertTrue(result[0].getValue()==0); 84 | Assert.assertTrue(result[1].getValue()==1); 85 | Assert.assertTrue(result[2].getValue()==2); 86 | Assert.assertTrue(result[3].getValue()==3); 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/graph/test/DepthFirstTraversalTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import junit.framework.Assert; 7 | 8 | import org.junit.Test; 9 | 10 | import com.jwetherell.algorithms.data_structures.Graph; 11 | import com.jwetherell.algorithms.graph.DepthFirstTraversal; 12 | 13 | public class DepthFirstTraversalTest { 14 | 15 | private static final byte[][] adjacencyMatrix = new byte[4][4]; 16 | static { 17 | // v0 18 | adjacencyMatrix[0][1] = 1; 19 | adjacencyMatrix[0][2] = 1; 20 | // v1 21 | adjacencyMatrix[1][2] = 1; 22 | // v2 23 | adjacencyMatrix[2][0] = 1; 24 | adjacencyMatrix[2][3] = 1; 25 | // v3 26 | adjacencyMatrix[3][3] = 1; 27 | } 28 | 29 | @Test 30 | public void test0() { 31 | final int[] result = DepthFirstTraversal.depthFirstTraversal(4, adjacencyMatrix, 2); 32 | Assert.assertTrue(result[0]==2); 33 | Assert.assertTrue(result[1]==0); 34 | Assert.assertTrue(result[2]==1); 35 | Assert.assertTrue(result[3]==3); 36 | } 37 | 38 | @Test 39 | public void test1() { 40 | final int[] result = DepthFirstTraversal.depthFirstTraversal(4, adjacencyMatrix, 0); 41 | Assert.assertTrue(result[0]==0); 42 | Assert.assertTrue(result[1]==1); 43 | Assert.assertTrue(result[2]==2); 44 | Assert.assertTrue(result[3]==3); 45 | } 46 | 47 | private static final List> vertices = new ArrayList>(); 48 | private static final List> edges = new ArrayList>(); 49 | 50 | private static final Graph.Vertex v0 = new Graph.Vertex(0); 51 | private static final Graph.Vertex v1 = new Graph.Vertex(1); 52 | private static final Graph.Vertex v2 = new Graph.Vertex(2); 53 | private static final Graph.Vertex v3 = new Graph.Vertex(3); 54 | 55 | static { 56 | vertices.add(v0); 57 | vertices.add(v1); 58 | vertices.add(v2); 59 | vertices.add(v3); 60 | 61 | edges.add(new Graph.Edge(0, v0, v1)); 62 | edges.add(new Graph.Edge(0, v0, v2)); 63 | edges.add(new Graph.Edge(0, v1, v2)); 64 | edges.add(new Graph.Edge(0, v2, v0)); 65 | edges.add(new Graph.Edge(0, v2, v3)); 66 | edges.add(new Graph.Edge(0, v3, v3)); 67 | } 68 | 69 | private static final Graph graph = new Graph(Graph.TYPE.DIRECTED, vertices, edges); 70 | 71 | @Test 72 | public void test2() { 73 | final Graph.Vertex[] result = DepthFirstTraversal.depthFirstTraversal(graph, v2); 74 | Assert.assertTrue(result[0].getValue()==2); 75 | Assert.assertTrue(result[1].getValue()==0); 76 | Assert.assertTrue(result[2].getValue()==1); 77 | Assert.assertTrue(result[3].getValue()==3); 78 | } 79 | 80 | @Test 81 | public void test3() { 82 | final Graph.Vertex[] result = DepthFirstTraversal.depthFirstTraversal(graph, v0); 83 | Assert.assertTrue(result[0].getValue()==0); 84 | Assert.assertTrue(result[1].getValue()==1); 85 | Assert.assertTrue(result[2].getValue()==2); 86 | Assert.assertTrue(result[3].getValue()==3); 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/graph/test/EdmondsKarpTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph.test; 2 | 3 | import com.jwetherell.algorithms.graph.EdmondsKarp; 4 | 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertTrue; 8 | 9 | 10 | /** 11 | * Created by mateusz on 27.02.17. 12 | */ 13 | public class EdmondsKarpTest { 14 | 15 | @Test 16 | public void Test1() { 17 | int A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6; 18 | EdmondsKarp ek = new EdmondsKarp(7, 11); 19 | ek.addEdge(A, D, 3); 20 | ek.addEdge(D, F, 6); 21 | ek.addEdge(A, B, 3); 22 | ek.addEdge(E, B, 1); 23 | ek.addEdge(E, G, 1); 24 | ek.addEdge(F, G, 9); 25 | ek.addEdge(D, E, 2); 26 | ek.addEdge(B, C, 4); 27 | ek.addEdge(C, A, 3); 28 | ek.addEdge(C, D, 1); 29 | ek.addEdge(C, E, 2); 30 | assertTrue(ek.getMaxFlow(A, G) == 5); 31 | } 32 | 33 | @Test 34 | public void Test2() { 35 | EdmondsKarp ek = new EdmondsKarp(2, 1); 36 | ek.addEdge(1, 0, 10); 37 | assertTrue(ek.getMaxFlow(0, 1) == 0); 38 | assertTrue(ek.getMaxFlow(1, 0) == 10); 39 | } 40 | 41 | @Test 42 | public void Test3() { 43 | EdmondsKarp ek = new EdmondsKarp(4, 5); 44 | ek.addEdge(0, 1, 1000); 45 | ek.addEdge(0, 2, 1000); 46 | ek.addEdge(1, 3, 1000); 47 | ek.addEdge(2, 3, 1000); 48 | ek.addEdge(1, 2, 1); 49 | assertTrue(ek.getMaxFlow(0, 3) == 2000); 50 | } 51 | 52 | @Test 53 | public void Test4() { 54 | EdmondsKarp ek = new EdmondsKarp(6, 8); 55 | ek.addEdge(0, 1, 3); 56 | ek.addEdge(0, 3, 3); 57 | ek.addEdge(1, 3, 2); 58 | ek.addEdge(1, 2, 3); 59 | ek.addEdge(3, 4, 2); 60 | ek.addEdge(4, 5, 3); 61 | ek.addEdge(2, 4, 4); 62 | ek.addEdge(2, 5, 2); 63 | assertTrue(ek.getMaxFlow(0, 5) == 5); 64 | } 65 | /* 66 | public static void main(String[] a) { 67 | int A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6; 68 | EdmondsKarp ek = new EdmondsKarp(7, 11); 69 | ek.AddEdge(A, D, 3); 70 | ek.AddEdge(D, F, 6); 71 | ek.AddEdge(A, B, 3); 72 | ek.AddEdge(E, B, 1); 73 | ek.AddEdge(E, G, 1); 74 | ek.AddEdge(F, G, 9); 75 | ek.AddEdge(D, E, 2); 76 | ek.AddEdge(B, C, 4); 77 | ek.AddEdge(C, A, 3); 78 | ek.AddEdge(C, D, 1); 79 | ek.AddEdge(C, E, 2); 80 | System.out.println(ek.GetMaxFlow(0, 6)); 81 | EdmondsKarp ek2 = new EdmondsKarp(2, 1); 82 | ek2.AddEdge(1, 0, 10); 83 | System.out.println(ek2.GetMaxFlow(0, 1)); 84 | System.out.println(ek2.GetMaxFlow(1, 0)); 85 | } 86 | */ 87 | } 88 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/graph/test/PushRelabelTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.graph.test; 2 | 3 | import com.jwetherell.algorithms.data_structures.Graph; 4 | import com.jwetherell.algorithms.graph.PushRelabel; 5 | import org.junit.Test; 6 | 7 | import java.util.Map; 8 | import java.util.TreeMap; 9 | 10 | import static org.junit.Assert.assertTrue; 11 | 12 | public class PushRelabelTest { 13 | 14 | private static class ExampleInput1 { 15 | 16 | final Graph.Vertex v1 = new Graph.Vertex(1); 17 | final Graph.Vertex v2 = new Graph.Vertex(2); 18 | final Graph.Vertex v3 = new Graph.Vertex(3); 19 | final Graph.Vertex v4 = new Graph.Vertex(4); 20 | 21 | final Graph.Edge e1_2 = new Graph.Edge(1, v1, v2); 22 | final Graph.Edge e1_3 = new Graph.Edge(1, v1, v3); 23 | final Graph.Edge e2_3 = new Graph.Edge(1, v2, v3); 24 | final Graph.Edge e3_2 = new Graph.Edge(1, v3, v2); 25 | final Graph.Edge e2_4 = new Graph.Edge(1, v2, v4); 26 | final Graph.Edge e3_4 = new Graph.Edge(1, v3, v4); 27 | 28 | final Map, Long> capacities = new TreeMap, Long>(); 29 | { 30 | capacities.put(e1_2, 3L); 31 | capacities.put(e1_3, 5L); 32 | capacities.put(e3_2, 3L); 33 | capacities.put(e2_3, 2L); 34 | capacities.put(e2_4, 7L); 35 | capacities.put(e3_4, 1L); 36 | } 37 | 38 | final Graph.Vertex source = v1; 39 | final Graph.Vertex sink = v4; 40 | } 41 | 42 | @Test 43 | public void testPushRelabel1() { 44 | final ExampleInput1 exampleInput = new ExampleInput1(); 45 | assertTrue(PushRelabel.getMaximumFlow(exampleInput.capacities, exampleInput.source, exampleInput.sink) == 7); 46 | } 47 | 48 | private static class ExampleInput2 { 49 | 50 | final Graph.Vertex v0 = new Graph.Vertex(0); 51 | final Graph.Vertex v1 = new Graph.Vertex(1); 52 | final Graph.Vertex v2 = new Graph.Vertex(2); 53 | final Graph.Vertex v3 = new Graph.Vertex(3); 54 | final Graph.Vertex v4 = new Graph.Vertex(4); 55 | final Graph.Vertex v5 = new Graph.Vertex(5); 56 | 57 | final Graph.Edge e0_1 = new Graph.Edge(1, v0, v1); 58 | final Graph.Edge e0_2 = new Graph.Edge(1, v0, v2); 59 | final Graph.Edge e1_2 = new Graph.Edge(1, v1, v2); 60 | final Graph.Edge e1_3 = new Graph.Edge(1, v1, v3); 61 | final Graph.Edge e2_1 = new Graph.Edge(1, v2, v1); 62 | final Graph.Edge e2_4 = new Graph.Edge(1, v2, v4); 63 | final Graph.Edge e3_2 = new Graph.Edge(1, v3, v2); 64 | final Graph.Edge e3_5 = new Graph.Edge(1, v3, v5); 65 | final Graph.Edge e4_3 = new Graph.Edge(1, v4, v3); 66 | final Graph.Edge e4_5 = new Graph.Edge(1, v4, v5); 67 | 68 | final Map, Long> capacities = new TreeMap, Long>(); 69 | { 70 | capacities.put(e0_1, 16L); 71 | capacities.put(e0_2, 13L); 72 | capacities.put(e1_2, 10L); 73 | capacities.put(e1_3, 12L); 74 | capacities.put(e2_1, 4L); 75 | capacities.put(e2_4, 14L); 76 | capacities.put(e3_2, 9L); 77 | capacities.put(e3_5, 20L); 78 | capacities.put(e4_3, 7L); 79 | capacities.put(e4_5, 4L); 80 | } 81 | 82 | final Graph.Vertex source = v0; 83 | final Graph.Vertex sink = v5; 84 | } 85 | 86 | @Test 87 | public void testPushRelabel2() { 88 | final ExampleInput2 exampleInput = new ExampleInput2(); 89 | assertTrue(PushRelabel.getMaximumFlow(exampleInput.capacities, exampleInput.source, exampleInput.sink) == 23); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/CoprimesTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import com.jwetherell.algorithms.mathematics.Coprimes; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class CoprimesTest { 12 | 13 | @Test 14 | public void totientTest(){ 15 | final List args = Arrays.asList(1L, 17L, 96L, 498L, 4182119424L); 16 | final List expected = Arrays.asList(1L, 16L, 32L, 164L, 1194891264L); 17 | 18 | for(int i = 0; i < args.size(); i++) 19 | assertEquals(expected.get(i), Coprimes.getNumberOfCoprimes(args.get(i))); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import org.junit.Test; 4 | 5 | import com.jwetherell.algorithms.mathematics.DiscreteLogarithm; 6 | 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class DiscreteLogarithmTest { 10 | 11 | @Test 12 | public void shouldCountDiscreteLogarithm() { 13 | final long a = 3; 14 | final long b = 4; 15 | final long p = 7; 16 | final long expectedX = 4; 17 | 18 | final long x = DiscreteLogarithm.countDiscreteLogarithm(a, b, p); 19 | assertTrue(x == expectedX); 20 | } 21 | 22 | @Test 23 | public void shouldCountDiscreteLogarithm2() { 24 | final long a = 2; 25 | final long b = 64; 26 | final long p = 101; 27 | final long expectedX = 6; 28 | 29 | final long x = DiscreteLogarithm.countDiscreteLogarithm(a, b, p); 30 | assertTrue(x == expectedX); 31 | } 32 | 33 | @Test 34 | public void shouldNotCountDiscreteLogarithm() { 35 | final long a = 4; 36 | final long b = 5; 37 | final long p = 7; 38 | final long expectedX = -1; 39 | 40 | final long x = DiscreteLogarithm.countDiscreteLogarithm(a, b, p); 41 | assertTrue(x == expectedX); 42 | } 43 | } -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import com.jwetherell.algorithms.mathematics.Exponentiation; 9 | 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | public class ExponentiationTest { 14 | 15 | @Test 16 | public void recusriveExponentiationTest() { 17 | final List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); 18 | final List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); 19 | final List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); 20 | 21 | for (int i = 0; i < expectedResultList.size(); i++) 22 | assertEquals(expectedResultList.get(i), Exponentiation.recursiveExponentiation(baseList.get(i), exponentList.get(i))); 23 | } 24 | 25 | @Test 26 | public void fastRecusriveExponentiationTest() { 27 | final List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); 28 | final List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); 29 | final List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); 30 | 31 | for (int i = 0; i < expectedResultList.size(); i++) 32 | assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiation(baseList.get(i), exponentList.get(i))); 33 | } 34 | 35 | @Test 36 | public void fastRecusriveExponentiationModuloTest() { 37 | final List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24, 2); 38 | final List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5, 1089); 39 | final List divisorList = Arrays.asList(2, 6, 3, 2, 9, 11, 5, 2179); 40 | final List expectedResultList = Arrays.asList(1, 2, 1, 0, 1, 8, 4, 2178); 41 | 42 | for (int i = 0; i < expectedResultList.size(); i++) 43 | assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiationModulo(baseList.get(i), exponentList.get(i), divisorList.get(i))); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/GCDTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | import com.jwetherell.algorithms.mathematics.GreatestCommonDivisor; 9 | 10 | 11 | public class GCDTest { 12 | 13 | @Test 14 | public void testRecursiveGCD() { 15 | assertEquals(3, GreatestCommonDivisor.gcdUsingRecursion(15, 138)); 16 | assertEquals(79, GreatestCommonDivisor.gcdUsingRecursion(79, -79)); 17 | assertEquals(750, GreatestCommonDivisor.gcdUsingRecursion(-750*1000000009L, -750*123)); 18 | } 19 | 20 | @Test 21 | public void testEuclideanGCD() { 22 | long x = 1989; 23 | long y = 867; 24 | long gcd = GreatestCommonDivisor.gcdUsingEuclides(x, y); 25 | long check = 51; 26 | assertTrue("Euclids GCD error. expected="+check+" got="+gcd, (gcd==check)); 27 | 28 | x = 567; 29 | y = 56; 30 | gcd = GreatestCommonDivisor.gcdUsingEuclides(x, y); 31 | check = 7; 32 | assertTrue("Euclids GCD error. expected="+check+" got="+gcd, (gcd==check)); 33 | 34 | x = 10002345; 35 | y = 67885; 36 | gcd = GreatestCommonDivisor.gcdUsingEuclides(x, y); 37 | check = 5; 38 | assertTrue("Euclids GCD error. expected="+check+" got="+gcd, (gcd==check)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import com.jwetherell.algorithms.data_structures.Matrix; 4 | import com.jwetherell.algorithms.mathematics.LUDecomposition; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class LUDecompositionTest { 10 | 11 | private boolean epsiMatrixCompare(Matrix a, Matrix b, double epsi) { 12 | if (a.getRows() != b.getRows() || a.getCols() != b.getCols()) { 13 | throw new IllegalArgumentException("Matrices are not the same shape"); 14 | } 15 | for (int i = 0; i < a.getRows(); i++) { 16 | for (int j = 0; j < a.getCols(); j++) { 17 | if (Math.abs(a.get(i, j) - b.get(i, j)) > epsi) { 18 | return false; 19 | } 20 | } 21 | } 22 | return true; 23 | } 24 | 25 | @Test 26 | public void decompositionTest1() throws Exception { 27 | Double[][] m = new Double[][]{{4.0, 3.0}, {6.0, 3.0}}; 28 | Double[][] resultL = new Double[][]{{1.0, 0.0}, {2.0 / 3.0, 1.0}}; 29 | Double[][] resultU = new Double[][]{{6.0, 3.0}, {0.0, 1.0}}; 30 | 31 | LUDecomposition luDecomposition = new LUDecomposition(new Matrix(2, 2, m)); 32 | assertTrue(epsiMatrixCompare(luDecomposition.getL(), new Matrix(2, 2, resultL), 10e-4)); 33 | assertTrue(epsiMatrixCompare(luDecomposition.getU(), new Matrix(2, 2, resultU), 10e-4)); 34 | } 35 | 36 | @Test 37 | public void decompositionTest2() throws Exception { 38 | Double[][] m = new Double[][]{{5.0, 3.0, 2.0}, {1.0, 2.0, 0.0}, {3.0, 0.0, 4.0}}; 39 | Double[][] resultL = new Double[][]{{1.0, 0.0, 0.0}, {0.6, 1.0, 0.0}, {0.2, -0.7778, 1.0}}; 40 | Double[][] resultU = new Double[][]{{5.0, 3.0, 2.0}, {0.0, -1.8, 2.8}, {0.0, 0.0, 1.778}}; 41 | 42 | LUDecomposition luDecomposition = new LUDecomposition(new Matrix(3, 3, m)); 43 | assertTrue(epsiMatrixCompare(luDecomposition.getL(), new Matrix(3, 3, resultL), 10e-4)); 44 | assertTrue(epsiMatrixCompare(luDecomposition.getU(), new Matrix(3, 3, resultU), 10e-4)); 45 | } 46 | } -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/PermutationsTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | import com.jwetherell.algorithms.mathematics.Permutations; 12 | 13 | public class PermutationsTest { 14 | 15 | @Test 16 | public void test1NumberOfPermutations() { 17 | final Integer[] numbers = {1,2,3,4}; 18 | final int expectedNumberOfPermutations = 24; 19 | assertEquals(expectedNumberOfPermutations, (Permutations.getAllPermutations(numbers)).size()); 20 | } 21 | 22 | @Test 23 | public void test2NumberOfPermutations() { 24 | final Integer[] numbers = {3,4,2}; 25 | final int expectedNumberOfPermutations = 6; 26 | assertEquals(expectedNumberOfPermutations, (Permutations.getAllPermutations(numbers)).size()); 27 | } 28 | 29 | @Test 30 | public void test3NumberOfPermutations() { 31 | final Integer[] numbers = {3,4,2,5,4,9}; 32 | final int expectedNumberOfPermutations = 720; 33 | assertEquals(expectedNumberOfPermutations, (Permutations.getAllPermutations(numbers)).size()); 34 | } 35 | 36 | @Test 37 | public void testComparePermutations() { 38 | final Integer[] numbers = {4,2}; 39 | 40 | final LinkedList firstPermutation = new LinkedList(); 41 | firstPermutation.add(4); 42 | firstPermutation.add(2); 43 | 44 | final LinkedList secondPermutation = new LinkedList(); 45 | secondPermutation.add(2); 46 | secondPermutation.add(4); 47 | 48 | final LinkedList> allPermutations = new LinkedList>(); 49 | allPermutations.add(firstPermutation); 50 | allPermutations.add(secondPermutation); 51 | 52 | final List> result = Permutations.getAllPermutations(numbers); 53 | assertTrue("allPermutations="+allPermutations+" result="+result, allPermutations.equals(result)); 54 | } 55 | 56 | @Test 57 | public void testPermutation1() { 58 | final String string = "abc"; 59 | final String[] list = Permutations.permutations(string); 60 | Assert.assertTrue(list[0].equals("abc")); 61 | Assert.assertTrue(list[5].equals("cba")); 62 | } 63 | 64 | @Test 65 | public void testPermutation2() { 66 | final String string = "abcd"; 67 | final String[] list = Permutations.permutations(string); 68 | Assert.assertTrue(list[0].equals("abcd")); 69 | Assert.assertTrue(list[5].equals("adcb")); 70 | Assert.assertTrue(list[11].equals("bdca")); 71 | Assert.assertTrue(list[17].equals("cdba")); 72 | Assert.assertTrue(list[23].equals("dcba")); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTest.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | import com.jwetherell.algorithms.mathematics.RamerDouglasPeucker; 10 | 11 | public class RamerDouglasPeuckerTest { 12 | 13 | @Test 14 | public void test1() { 15 | final List list = new ArrayList(); 16 | list.add(new Double[]{3.14d, 5.2d}); 17 | list.add(new Double[]{5.7d, 8.1d}); 18 | list.add(new Double[]{4.6d, -1.3d}); 19 | 20 | final List simplified = RamerDouglasPeucker.douglasPeucker(list, 5.0d); 21 | final List expected = new ArrayList(); 22 | expected.add(list.get(0)); 23 | expected.add(list.get(2)); 24 | Assert.assertTrue(simplified.size()==2 && simplified.equals(expected)); 25 | } 26 | 27 | @Test 28 | public void test2() { 29 | final List list = new ArrayList(); 30 | list.add(new Double[]{0.0d,0.0d}); 31 | list.add(new Double[]{2.5d, 3.0d}); 32 | list.add(new Double[]{5.0d, 0.0d}); 33 | 34 | final List simplified = RamerDouglasPeucker.douglasPeucker(list, 2.9d); 35 | final List expected = new ArrayList(); 36 | expected.add(list.get(0)); 37 | expected.add(list.get(1)); 38 | expected.add(list.get(2)); 39 | Assert.assertTrue(simplified.size()==3 && simplified.equals(expected)); 40 | } 41 | 42 | @Test 43 | public void test3() { 44 | final List list = new ArrayList(); 45 | list.add(new Double[]{0.0d,0.0d}); 46 | list.add(new Double[]{2.5d, 3.0d}); 47 | list.add(new Double[]{5.0d, 0.0d}); 48 | 49 | final List simplified = RamerDouglasPeucker.douglasPeucker(list, 3.0d); 50 | final List expected = new ArrayList(); 51 | expected.add(list.get(0)); 52 | expected.add(list.get(2)); 53 | Assert.assertTrue(simplified.size()==2 && simplified.equals(expected)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/timing/ExponentiationTiming.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.timing; 2 | 3 | import com.jwetherell.algorithms.mathematics.Exponentiation; 4 | 5 | /** 6 | * Notice that 2^1000 is out of integer range so returned result is not correct. 7 | * It is a reason why exponentiation modulo is useful. 8 | * But it does not matter when you want to compare speed of these two algorithms. 9 | */ 10 | public class ExponentiationTiming { 11 | public static void main(String[] args) { 12 | System.out.println("Calculating a power using a recursive function."); 13 | long before = System.nanoTime(); 14 | Exponentiation.recursiveExponentiation(2, 1000); 15 | long after = System.nanoTime(); 16 | System.out.println("Computed in " + (after - before) + " ns"); 17 | 18 | System.out.println("Calculating a power using a fast recursive function."); 19 | before = System.nanoTime(); 20 | Exponentiation.fastRecursiveExponentiation(2, 1000); 21 | after = System.nanoTime(); 22 | System.out.println("Computed in " + (after - before) + " ns"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/mathematics/timing/GCDTiming.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.mathematics.timing; 2 | 3 | import java.text.DecimalFormat; 4 | 5 | import com.jwetherell.algorithms.mathematics.GreatestCommonDivisor; 6 | 7 | public class GCDTiming { 8 | 9 | private static final DecimalFormat FORMAT = new DecimalFormat("#.######"); 10 | 11 | public static void main(String[] args) { 12 | // Euclidean 13 | { 14 | System.out.println("Euclid's Greatest Common Divisor."); 15 | long x = 1989; 16 | long y = 867; 17 | long before = System.nanoTime(); 18 | GreatestCommonDivisor.gcdUsingEuclides(x, y); 19 | long after = System.nanoTime(); 20 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 21 | System.out.println(); 22 | System.gc(); 23 | } 24 | // Recursion 25 | { 26 | System.out.println("Recursive's Greatest Common Divisor."); 27 | long x = 1989; 28 | long y = 867; 29 | long before = System.nanoTime(); 30 | GreatestCommonDivisor.gcdUsingRecursion(x, y); 31 | long after = System.nanoTime(); 32 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 33 | System.out.println(); 34 | System.gc(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/sequence/timing/SequencesTiming.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.sequence.timing; 2 | 3 | import java.text.DecimalFormat; 4 | 5 | import com.jwetherell.algorithms.sequence.FibonacciSequence; 6 | import com.jwetherell.algorithms.sequence.ArithmeticProgression; 7 | 8 | public class SequencesTiming { 9 | 10 | private static final DecimalFormat FORMAT = new DecimalFormat("#.######"); 11 | 12 | public static void main(String[] args) { 13 | { 14 | // TOTAL OF A SEQUENCE OF NUMBERS 15 | int start = 14; 16 | int length = 10000; 17 | System.out.println("Computing sequence total using a loop."); 18 | long before = System.nanoTime(); 19 | ArithmeticProgression.sequenceTotalUsingLoop(start, length); 20 | long after = System.nanoTime(); 21 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 22 | System.gc(); 23 | 24 | System.out.println("Computing sequence total using Triangular Numbers."); 25 | before = System.nanoTime(); 26 | ArithmeticProgression.sequenceTotalUsingTriangularNumbers(start, length); 27 | after = System.nanoTime(); 28 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 29 | System.out.println(); 30 | System.gc(); 31 | } 32 | 33 | { 34 | // COMPUTE FIBONACCI SEQUENCE 35 | System.out.println("Computing Fibonacci sequence total using a loop."); 36 | int element = 25; 37 | long before = System.nanoTime(); 38 | FibonacciSequence.fibonacciSequenceUsingLoop(element); 39 | long after = System.nanoTime(); 40 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 41 | System.gc(); 42 | 43 | System.out.println("Computing Fibonacci sequence total using Recursion."); 44 | before = System.nanoTime(); 45 | FibonacciSequence.fibonacciSequenceUsingRecursion(element); 46 | after = System.nanoTime(); 47 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 48 | System.gc(); 49 | 50 | System.out.println("Computing Fibonacci sequence total using Matrix."); 51 | before = System.nanoTime(); 52 | FibonacciSequence.fibonacciSequenceUsingMatrixMultiplication(element); 53 | after = System.nanoTime(); 54 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 55 | System.gc(); 56 | 57 | System.out.println("Computing Fibonacci sequence total using Binet's formula."); 58 | before = System.nanoTime(); 59 | FibonacciSequence.fibonacciSequenceUsingBinetsFormula(element); 60 | after = System.nanoTime(); 61 | System.out.println("Computed in " + FORMAT.format(after - before) + " ns"); 62 | System.out.println(); 63 | System.gc(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/strings/test/KnuthMorrisPrattTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.strings.test; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import org.junit.Test; 9 | 10 | import com.jwetherell.algorithms.strings.KnuthMorrisPratt; 11 | 12 | public class KnuthMorrisPrattTests { 13 | 14 | @Test 15 | @SuppressWarnings("unchecked") 16 | public void getPrefixSuffixes() throws Exception { 17 | final List data = Arrays.asList( 18 | new Object[][]{ 19 | {"", Arrays.asList()}, 20 | {"a", Arrays.asList(0)}, 21 | {"aaa", Arrays.asList(0, 1, 2)}, 22 | {"abbabb", Arrays.asList(0, 0, 0, 1, 2, 3)}, 23 | {"bbabbbbaab", Arrays.asList(0, 1, 0, 1, 2, 2, 2, 3, 0, 1)}, 24 | { 25 | "( ͡° ͜ʖ ͡° )( ͡° a( ͡° ͜ʖ ͡°",//"( ͡° ͜ʖ ͡° )( ͡° a( ͡° ͜ʖ ͡°", 26 | Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 27 | } 28 | } 29 | ); 30 | for (Object[] testCase: data) { 31 | String input = (String) testCase[0]; 32 | List expected = (List) testCase[1]; 33 | List result = KnuthMorrisPratt.getPrefSufTable(input); 34 | assertEquals(expected, result); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/strings/test/ManacherTests.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.strings.test; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import java.util.List; 5 | import java.util.Arrays; 6 | import com.jwetherell.algorithms.strings.Manacher; 7 | import org.junit.Test; 8 | 9 | public class ManacherTests { 10 | 11 | @Test 12 | public void testGetLongestPalindromicSubstring() throws Exception { 13 | final List data = Arrays.asList( 14 | new Object[][]{ 15 | {null, null}, 16 | {"", ""}, 17 | {"a", "a"}, 18 | {"aa", "aa"}, 19 | {"aaa", "aaa"}, 20 | {"abaa", "aba"}, 21 | {"abba", "abba"}, 22 | {"abbaaa", "abba"}, 23 | {"abbabb", "bbabb"}, 24 | {"bananas", "anana"}, 25 | {"bakskskba", "ksksk"}, 26 | {"itisneveroddoreven", "neveroddoreven"}, 27 | {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", "A"}, 28 | {"I like bananas", "anana"} 29 | 30 | } 31 | ); 32 | for (Object[] testCase: data) { 33 | String input = (String) testCase[0]; 34 | String expected = (String) testCase[1]; 35 | String result = Manacher.getLongestPalindromicSubstring(input); 36 | assertEquals(expected, result); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/com/jwetherell/algorithms/strings/test/StringRotation.java: -------------------------------------------------------------------------------- 1 | package com.jwetherell.algorithms.strings.test; 2 | 3 | import com.jwetherell.algorithms.strings.Rotation; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.*; 7 | 8 | public class StringRotation { 9 | 10 | private String reverse(String text) { 11 | return new StringBuilder(text).reverse().toString(); 12 | } 13 | 14 | @Test 15 | public void minimalRotationTest() { 16 | assertEquals("", 17 | Rotation.getLexicographicallyMinimalRotation("")); 18 | 19 | assertEquals("a", 20 | Rotation.getLexicographicallyMinimalRotation("a")); 21 | 22 | assertEquals("abcdefgh", 23 | Rotation.getLexicographicallyMinimalRotation("abcdefgh")); 24 | 25 | assertEquals("abcdefgh", 26 | Rotation.getLexicographicallyMinimalRotation("bcdefgha")); 27 | 28 | assertEquals("abbbbbbb", 29 | Rotation.getLexicographicallyMinimalRotation("bbbbbabb")); 30 | 31 | 32 | StringBuilder builder = new StringBuilder(); 33 | for(char c = 'Z'; c > 'A'; c--) { 34 | for(int i = 0; i<4000; i++) 35 | builder.append(c); 36 | for(char c2 = c; c2 <= 'Z'; c2++) 37 | builder.append(c2); 38 | } 39 | String str = builder.toString(); 40 | 41 | assertEquals('A'+str+str, 42 | Rotation.getLexicographicallyMinimalRotation(str + 'A' + str)); 43 | 44 | assertEquals('A'+str+reverse(str)+str, 45 | Rotation.getLexicographicallyMinimalRotation(reverse(str) + str + 'A' + str)); 46 | } 47 | 48 | @Test 49 | public void maximalRotationTest() { 50 | assertEquals("", 51 | Rotation.getLexicographicallyMaximalRotation("")); 52 | 53 | assertEquals("a", 54 | Rotation.getLexicographicallyMaximalRotation("a")); 55 | 56 | assertEquals("habcdefg", 57 | Rotation.getLexicographicallyMaximalRotation("abcdefgh")); 58 | 59 | assertEquals("habcdefg", 60 | Rotation.getLexicographicallyMaximalRotation("habcdefg")); 61 | 62 | assertEquals("cbbbbbbb", 63 | Rotation.getLexicographicallyMaximalRotation("bbbbbcbb")); 64 | 65 | StringBuilder builder = new StringBuilder(); 66 | for(char c = 'A'; c < 'Z'; c++) { 67 | for(int i = 0; i<4000; i++) 68 | builder.append(c); 69 | for(char c2 = c; c2 >='A'; c2--) 70 | builder.append(c2); 71 | } 72 | String str = builder.toString(); 73 | 74 | assertEquals('Z'+str+str, 75 | Rotation.getLexicographicallyMaximalRotation(str + 'Z' + str)); 76 | 77 | assertEquals('Z'+str+reverse(str)+str, 78 | Rotation.getLexicographicallyMaximalRotation(reverse(str) + str + 'Z' + str)); 79 | } 80 | } 81 | --------------------------------------------------------------------------------