├── src ├── main │ ├── java │ │ └── org │ │ │ └── paukov │ │ │ ├── tool │ │ │ ├── package.html │ │ │ └── IntExpressionParser.java │ │ │ └── combinatorics │ │ │ ├── package.html │ │ │ ├── IFilter.java │ │ │ ├── combination │ │ │ ├── multi │ │ │ │ ├── package.html │ │ │ │ ├── MultiCombinationGenerator.java │ │ │ │ └── MultiCombinationIterator.java │ │ │ └── simple │ │ │ │ ├── package.html │ │ │ │ ├── SimpleCombinationGenerator.java │ │ │ │ └── SimpleCombinationIterator.java │ │ │ ├── IGenerator.java │ │ │ ├── partition │ │ │ ├── package.html │ │ │ ├── PartitionGenerator.java │ │ │ └── PartitionIterator.java │ │ │ ├── cartesian │ │ │ ├── CartesianProductGenerator.java │ │ │ └── CartesianProductIterator.java │ │ │ ├── ICombinatoricsVector.java │ │ │ ├── composition │ │ │ ├── package.html │ │ │ ├── IntegerCompositionGenerator.java │ │ │ ├── IntegerCompositionIterator.java │ │ │ ├── CompositionIterator.java │ │ │ └── CompositionGenerator.java │ │ │ ├── util │ │ │ ├── package.html │ │ │ └── ComplexCombinationIterator.java │ │ │ ├── IntegerGenerator.java │ │ │ ├── subsets │ │ │ ├── package.html │ │ │ ├── IntegerSubListIterator.java │ │ │ ├── SubListIterator.java │ │ │ ├── SubSetIterator.java │ │ │ ├── IntegerSubSetIterator.java │ │ │ ├── IntegerSubSetGenerator.java │ │ │ └── SubSetGenerator.java │ │ │ ├── permutations │ │ │ ├── package.html │ │ │ ├── PermutationIterator.java │ │ │ ├── PermutationWithRepetitionIterator.java │ │ │ ├── PermutationWithRepetitionGenerator.java │ │ │ ├── PermutationGenerator.java │ │ │ └── DuplicatedPermutationIterator.java │ │ │ ├── Generator.java │ │ │ ├── IntegerFactory.java │ │ │ ├── IntegerVector.java │ │ │ └── CombinatoricsVector.java │ └── resources │ │ └── META-INF │ │ └── README.txt └── test │ └── java │ └── org │ └── paukov │ ├── tool │ └── IntExpressionPareserTest.java │ └── combinatorics │ ├── CombinatoricsFactoryTest.java │ ├── IntegerFactoryTest.java │ ├── cartesian │ └── CartesianProductTest.java │ ├── util │ └── UtilTest.java │ ├── IntegerVectorTest.java │ ├── CombinatoricsVectorTest.java │ ├── composition │ ├── IntegerCompositionTest.java │ └── CompositionTest.java │ └── partition │ └── PartitionsTest.java ├── .travis.yml ├── .gitignore ├── .project ├── .classpath ├── pom.xml └── LICENSE /src/main/java/org/paukov/tool/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains various tools. 6 | 7 | 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | dist: trusty 4 | 5 | jdk: 6 | - openjdk7 7 | - oraclejdk8 8 | 9 | script: mvn clean cobertura:cobertura coveralls:report 10 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains common classes and interfaces of the library such as 6 | ICombinatoricsVector, Generator and CombinatoricsFactory. 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .classpath 3 | .project 4 | .settings/ 5 | 6 | # Intellij 7 | .idea/ 8 | *.iml 9 | *.iws 10 | 11 | # Mac 12 | .DS_Store 13 | 14 | # Maven 15 | log/ 16 | target/ 17 | 18 | #Other files 19 | *.class 20 | 21 | # Mobile Tools for Java (J2ME) 22 | .mtj.tmp/ 23 | 24 | # Package Files # 25 | *.jar 26 | *.war 27 | *.ear 28 | 29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 30 | hs_err_pid* -------------------------------------------------------------------------------- /src/test/java/org/paukov/tool/IntExpressionPareserTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.tool; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | import org.junit.Test; 10 | import org.paukov.tool.IntExpressionParser; 11 | 12 | /** 13 | * @author Dmytro Paukov 14 | * 15 | */ 16 | public class IntExpressionPareserTest { 17 | 18 | @Test 19 | public void simpleTest() { 20 | String expr = "1+2*3*4+3*(2+2)-10"; 21 | int result = IntExpressionParser.eval(expr); 22 | assertEquals(27, result); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | combinatoricslib 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e.core.maven2Nature 21 | org.eclipse.jdt.core.javanature 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/IFilter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | /** 8 | * This is the interface for filtering the generated combinatorial vectors. 9 | * 10 | * @param Type of the elements 11 | * @author Dmytro Paukov 12 | * @version 2.0 13 | * @see IGenerator#generateFilteredObjects 14 | */ 15 | public interface IFilter { 16 | 17 | /** 18 | * This method defines a condition for a given value to be accepted by the 19 | * filter or not. 20 | * 21 | * @param index The index of the value. 22 | * @param value The value to be tested. 23 | * @return true if the value is accepted, otherwise false. 24 | */ 25 | boolean accepted(long index, T value); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/combination/multi/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the multicombinations generator (combinations with repetitions). 6 | 7 | 8 |

Multi-combinations

9 | 10 | A k-multicombination or k-combination with repetition of a finite set S is 11 | given by a sequence of k not necessarily distinct elements of S, where order 12 | is not taken into account. 13 |

14 | As an example. Suppose there are 2 types of fruits (apple and orange) at a 15 | grocery store, and you want to buy 3 pieces of fruit. You could select 16 |

22 |

23 | Generate 3-combinations with repetitions of the set (apple, orange). 24 |

25 |

26 |

27 |
28 | // Create the initial vector of (apple, orange)
29 | ICombinatoricsVector<String> initialVector = CombinatoricsFactory.createVector(new String[] {
30 | 		"apple", "orange" });
31 | 
32 | // Create a multi-combination generator to generate 3-combinations of
33 | // the initial vector
34 | Generator<String> gen = CombinatoricsFactory.createMultiCombinationGenerator(initialVector,3);
35 |  
36 | // Print all possible combinations
37 | for (ICombinatoricsVector<String> combination : gen) {
38 | 	System.out.println(combination);
39 | }
40 | 
41 |
42 |

43 | And the result of 4 multi-combinations 44 |

45 |

46 |
47 |    CombinatoricsVector=([apple, apple, apple], size=3)
48 |    CombinatoricsVector=([apple, apple, orange], size=3)
49 |    CombinatoricsVector=([apple, orange, orange], size=3)
50 |    CombinatoricsVector=([orange, orange, orange], size=3)
51 | 
52 |
53 |

54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/IGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | /** 11 | * This interface is implemented by all generic generators in the library. 12 | * 13 | * @param The type of the elements. 14 | * @author Dmytro Paukov 15 | * @version 2.0 16 | */ 17 | public interface IGenerator extends Iterable { 18 | 19 | /** 20 | * Returns core/original vector. This is a main vector which is used for 21 | * generating other objects. 22 | * 23 | * @return The original vector which was passed into a constructor as an initializing parameter. 24 | */ 25 | T getOriginalVector(); 26 | 27 | /** 28 | * Returns the number of the the generated objects/vectors. 29 | * 30 | * @return Number of the generated vectors. 31 | */ 32 | long getNumberOfGeneratedObjects(); 33 | 34 | /** 35 | * Creates an iterator for enumerating all generated objects/vectors. 36 | * 37 | * @return The iterator over the generated objects/vectors. 38 | */ 39 | Iterator iterator(); 40 | 41 | /** 42 | * Returns all generated vectors as a list. 43 | * 44 | * @return List of all generated objects/vectors. 45 | */ 46 | List generateAllObjects(); 47 | 48 | /** 49 | * Returns the generated vectors filtered by a filter. 50 | * 51 | * @param filter The filter to be applied to the generated result. 52 | * @return The list of the filtered vectors. 53 | * @see IFilter 54 | */ 55 | List generateFilteredObjects(IFilter filter); 56 | 57 | /** 58 | * Returns vectors as a list for specified range of indexes (from the 59 | * startIndex to stopIndex). 60 | * 61 | * @return List of the generated objects/vectors. 62 | */ 63 | List generateObjectsRange(long startIndex, long stopIndex); 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/combination/simple/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the simple combinations generator. 6 | 7 |

Simple combinations

8 |

9 | A simple k-combination of a finite set S is a subset of k distinct elements 10 | of S. Specifying a subset does not arrange them in a particular order. As an 11 | example, a poker hand can be described as a 5-combination of cards from a 12 | 52-card deck: the 5 cards of the hand are all distinct, and the order of the 13 | cards in the hand does not matter. 14 |

15 | For example, let's generate 3-combination of the set (red, black, white, green, blue). 16 |

17 |

18 |
19 | // Create the initial vector
20 | ICombinatoricsVector<String> initialVector = CombinatoricsFactory.createVector(new String[] {
21 | 		"red", "black", "white", "green", "blue" });
22 | 
23 | // Create a simple combination generator to generate 3-combinations of the
24 | // initial vector
25 | Generator<String> gen = CombinatoricsFactory.createSimpleCombinationGenerator(initialVector, 3);
26 | 
27 | // Print all possible combinations
28 | for (ICombinatoricsVector<String> combination : gen) {
29 | 	System.out.println(combination);
30 | }
31 | 
32 |
33 |

34 | And the result of 10 combinations 35 |

36 |

37 |
38 |    CombinatoricsVector=([red, black, white], size=3)
39 |    CombinatoricsVector=([red, black, green], size=3)
40 |    CombinatoricsVector=([red, black, blue], size=3)
41 |    CombinatoricsVector=([red, white, green], size=3)
42 |    CombinatoricsVector=([red, white, blue], size=3)
43 |    CombinatoricsVector=([red, green, blue], size=3)
44 |    CombinatoricsVector=([black, white, green], size=3)
45 |    CombinatoricsVector=([black, white, blue], size=3)
46 |    CombinatoricsVector=([black, green, blue], size=3)
47 |    CombinatoricsVector=([white, green, blue], size=3)
48 | 
49 |
50 |

51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/partition/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the integer partitions generator. 6 | 7 |

8 | In number theory, a partition of a positive integer n is a way of writing n 9 | as a sum of positive integers. Two sums that differ only in the order of 10 | their summands are considered to be the same partition; if order matters then 11 | the sum becomes a composition. A summand in a partition is also called a 12 | part. 13 |

14 | WARNING! Be careful because number of all partitions can be very high even 15 | for not great given N. 16 |

17 | The partitions of 5 are listed below: 18 |

    19 |
  1. 1 + 1 + 1 + 1 + 1 20 |
  2. 2 + 1 + 1 + 1 21 |
  3. 2 + 2 + 1 22 |
  4. 3 + 1 + 1 23 |
  5. 3 + 2 24 |
  6. 4 + 1 25 |
  7. 5 26 |
27 |

28 | The number of partitions of n is given by the partition function p(n). In 29 | number theory, the partition function p(n) represents the number of possible 30 | partitions of a natural number n, which is to say the number of distinct (and 31 | order independent) ways of representing n as a sum of natural numbers. 32 |

33 | Let's generate all possible partitions of 5: 34 |

35 |

36 | 37 |
38 | // Create an instance of the partition generator to generate all
39 | // possible partitions of 5
40 | Generator<Integer> gen = CombinatoricsFactory.createPartitionGenerator(5);
41 | 
42 | // Print the partitions
43 | for (ICombinatoricsVector<Integer> p : gen) {
44 | 	System.out.println(p);
45 | }
46 | 
47 | 48 |
49 |

50 | And the result of all 7 integer possible partitions 51 |

52 |

53 |
54 |   CombinatoricsVector=([1, 1, 1, 1, 1], size=5)
55 |   CombinatoricsVector=([2, 1, 1, 1], size=4)
56 |   CombinatoricsVector=([2, 2, 1], size=3)
57 |   CombinatoricsVector=([3, 1, 1], size=3)
58 |   CombinatoricsVector=([3, 2], size=2)
59 |   CombinatoricsVector=([4, 1], size=2)
60 |   CombinatoricsVector=([5], size=1)
61 | 
62 |
63 |

64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/cartesian/CartesianProductGenerator.java: -------------------------------------------------------------------------------- 1 | package org.paukov.combinatorics.cartesian; 2 | 3 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 4 | 5 | import java.util.Iterator; 6 | import org.paukov.combinatorics.Generator; 7 | import org.paukov.combinatorics.ICombinatoricsVector; 8 | 9 | /** 10 | * This generator generates Cartesian product from specified multiple lists. Set of lists is 11 | * specified in the constructor of generator to generate k-element Cartesian product, where k is the 12 | * size of the set of lists. 13 | * 14 | * A simple k-element Cartesian product of a finite sets S(1), S(2)...S(k) is a set of all ordered 15 | * pairs (x(1), x(2)...x(k), where x(1) ∈ S(1), x(2) ∈ S(2) ... x(k) ∈ S(k) 16 | * 17 | * Example. Generate 3-element Cartesian product from (1, 2, 3), (4, 5, 6), (7, 8, 9). 18 | * 19 | *

20 |  * ICombinatoricsVector<Integer> set01 = createVector(1, 2, 3);
21 |  * ICombinatoricsVector<Integer> set02 = createVector(4, 5, 6);
22 |  * ICombinatoricsVector<Integer> set03 = createVector(7, 8, 9);
23 |  *
24 |  *  Generator<Integer> cartesianProduct = createCartesianProductGenerator(set01, set02, set03);
25 |  * 
26 | * 27 | * @param Type of elements in the Cartesian product 28 | * @author Julius Iglesia, Dmytro Paukov 29 | * @version 2.2 30 | * @see CartesianProductIterator 31 | */ 32 | public class CartesianProductGenerator extends Generator { 33 | 34 | final ICombinatoricsVector> originalVector; 35 | 36 | /** 37 | * @param originalVector Vector which is used for generating the Cartesian product. 38 | */ 39 | public CartesianProductGenerator(ICombinatoricsVector> originalVector) { 40 | this.originalVector = createVector(originalVector); 41 | } 42 | 43 | @Override 44 | public ICombinatoricsVector getOriginalVector() { 45 | throw new UnsupportedOperationException(); 46 | } 47 | 48 | @Override 49 | public long getNumberOfGeneratedObjects() { 50 | long number = originalVector.getSize() > 0 ? 1 : 0; 51 | for (ICombinatoricsVector vector : originalVector) { 52 | number *= vector.getSize(); 53 | } 54 | return number; 55 | } 56 | 57 | @Override 58 | public Iterator> iterator() { 59 | return new CartesianProductIterator<>(this); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/CombinatoricsFactoryTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library Copyright 2012 Dmytro Paukov d.paukov@gmail.com 3 | */ 4 | package org.paukov.combinatorics; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertFalse; 8 | 9 | import java.util.Arrays; 10 | import org.junit.Test; 11 | 12 | /** 13 | * @author Dmytro Paukov 14 | */ 15 | public class CombinatoricsFactoryTest { 16 | 17 | @Test 18 | public void testRange1() { 19 | // create a combinatorics vector (1, 2, 3) 20 | ICombinatoricsVector vector = CombinatoricsFactory.range(3); 21 | 22 | assertEquals(3, vector.getSize()); 23 | assertFalse(vector.hasDuplicates()); 24 | 25 | assertEquals((Integer) 1, vector.getValue(0)); 26 | assertEquals((Integer) 2, vector.getValue(1)); 27 | assertEquals((Integer) 3, vector.getValue(2)); 28 | } 29 | 30 | @Test 31 | public void testRange2() { 32 | // create a combinatorics vector () 33 | ICombinatoricsVector vector = CombinatoricsFactory.range(0); 34 | 35 | System.out.println(vector); 36 | 37 | assertEquals(0, vector.getSize()); 38 | assertFalse(vector.hasDuplicates()); 39 | } 40 | 41 | @Test(expected = IllegalArgumentException.class) 42 | public void testRange3() { 43 | // create a combinatorics vector from -1 44 | CombinatoricsFactory.range(-1); 45 | } 46 | 47 | @Test 48 | public void testRangeFromTo1() { 49 | // create a combinatorics vector (2, 3, 4, 5) 50 | ICombinatoricsVector vector = CombinatoricsFactory.range(2, 5); 51 | 52 | assertEquals(4, vector.getSize()); 53 | assertFalse(vector.hasDuplicates()); 54 | 55 | assertEquals((Integer) 2, vector.getValue(0)); 56 | assertEquals((Integer) 3, vector.getValue(1)); 57 | assertEquals((Integer) 4, vector.getValue(2)); 58 | assertEquals((Integer) 5, vector.getValue(3)); 59 | } 60 | 61 | @Test 62 | public void testRangeFromTo2() { 63 | // create a combinatorics vector (2) 64 | ICombinatoricsVector vector = CombinatoricsFactory.range(2, 2); 65 | 66 | assertEquals(1, vector.getSize()); 67 | assertFalse(vector.hasDuplicates()); 68 | 69 | assertEquals((Integer) 2, vector.getValue(0)); 70 | } 71 | 72 | @Test(expected = IllegalArgumentException.class) 73 | public void testRangeFromTo3() { 74 | // create an error 75 | CombinatoricsFactory.range(2, 1); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/IntegerFactoryTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | import org.junit.Test; 10 | 11 | /** 12 | * @author Dmytro Paukov 13 | */ 14 | public class IntegerFactoryTest { 15 | 16 | @Test 17 | public void testRange1() { 18 | 19 | // create a combinatorics vector (1, 2, 3) 20 | IntegerVector vector = IntegerFactory.range(3); 21 | 22 | System.out.println(vector); 23 | 24 | assertEquals(3, vector.getSize()); 25 | assertEquals(false, vector.hasDuplicates()); 26 | 27 | assertEquals(1, vector.getValue(0)); 28 | assertEquals(2, vector.getValue(1)); 29 | assertEquals(3, vector.getValue(2)); 30 | 31 | } 32 | 33 | @Test 34 | public void testRange2() { 35 | 36 | // create a combinatorics vector () 37 | IntegerVector vector = IntegerFactory.range(0); 38 | 39 | System.out.println(vector); 40 | 41 | assertEquals(0, vector.getSize()); 42 | assertEquals(false, vector.hasDuplicates()); 43 | } 44 | 45 | @Test(expected = IllegalArgumentException.class) 46 | public void testRange3() { 47 | 48 | // create a combinatorics vector from -1 49 | IntegerFactory.range(-1); 50 | 51 | } 52 | 53 | @Test 54 | public void testRangeFromTo1() { 55 | 56 | // create a combinatorics vector (2, 3, 4, 5) 57 | IntegerVector vector = IntegerFactory.range(2, 5); 58 | 59 | System.out.println(vector); 60 | 61 | assertEquals(4, vector.getSize()); 62 | assertEquals(false, vector.hasDuplicates()); 63 | 64 | assertEquals(2, vector.getValue(0)); 65 | assertEquals(3, vector.getValue(1)); 66 | assertEquals(4, vector.getValue(2)); 67 | assertEquals(5, vector.getValue(3)); 68 | 69 | } 70 | 71 | @Test 72 | public void testRangeFromTo2() { 73 | 74 | // create a combinatorics vector (2) 75 | IntegerVector vector = IntegerFactory.range(2, 2); 76 | 77 | System.out.println(vector); 78 | 79 | assertEquals(1, vector.getSize()); 80 | assertEquals(false, vector.hasDuplicates()); 81 | 82 | assertEquals(2, vector.getValue(0)); 83 | } 84 | 85 | @Test(expected = IllegalArgumentException.class) 86 | public void testRangeFromTo3() { 87 | 88 | // create an error 89 | CombinatoricsFactory.range(2, 1); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/tool/IntExpressionParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.tool; 6 | 7 | import java.util.LinkedList; 8 | 9 | /** 10 | * @author Dmytro Paukov 11 | * @version 2.0 12 | */ 13 | public class IntExpressionParser { 14 | 15 | static public boolean isDelim(char c) { 16 | return c == ' '; 17 | } 18 | 19 | static public boolean isOperator(char c) { 20 | return c == '+' || c == '-' || c == '*' || c == '/' || c == '%'; 21 | } 22 | 23 | static public int priority(char op) { 24 | switch (op) { 25 | case '+': 26 | case '-': 27 | return 1; 28 | case '*': 29 | case '/': 30 | case '%': 31 | return 2; 32 | default: 33 | return -1; 34 | } 35 | } 36 | 37 | static public void processOperator(LinkedList st, char op) { 38 | int r = st.removeLast(); 39 | int l = st.removeLast(); 40 | switch (op) { 41 | case '+': 42 | st.add(l + r); 43 | break; 44 | case '-': 45 | st.add(l - r); 46 | break; 47 | case '*': 48 | st.add(l * r); 49 | break; 50 | case '/': 51 | st.add(l / r); 52 | break; 53 | case '%': 54 | st.add(l % r); 55 | break; 56 | } 57 | } 58 | 59 | public static int eval(String s) { 60 | LinkedList st = new LinkedList(); 61 | LinkedList op = new LinkedList(); 62 | for (int i = 0; i < s.length(); i++) { 63 | char c = s.charAt(i); 64 | if (isDelim(c)) { 65 | continue; 66 | } 67 | if (c == '(') { 68 | op.add('('); 69 | } else if (c == ')') { 70 | while (op.getLast() != '(') { 71 | processOperator(st, op.removeLast()); 72 | } 73 | op.removeLast(); 74 | } else if (isOperator(c)) { 75 | while (!op.isEmpty() && priority(op.getLast()) >= priority(c)) { 76 | processOperator(st, op.removeLast()); 77 | } 78 | op.add(c); 79 | } else { 80 | String operand = ""; 81 | while (i < s.length() && Character.isDigit(s.charAt(i))) { 82 | operand += s.charAt(i++); 83 | } 84 | --i; 85 | st.add(Integer.parseInt(operand)); 86 | } 87 | } 88 | while (!op.isEmpty()) { 89 | processOperator(st, op.removeLast()); 90 | } 91 | return st.get(0); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/ICombinatoricsVector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * This interface is implemented by all generic combinatorics vectors of the 11 | * library. 12 | * 13 | * @param Type of the elements 14 | * @author Dmytro Paukov 15 | * @version 2.0 16 | * @see CombinatoricsFactory 17 | */ 18 | public interface ICombinatoricsVector extends Iterable { 19 | 20 | /** 21 | * Sets value to position index. If the index is out of bounds 22 | * the value will be added at the end of the vector 23 | * 24 | * @param index Position of element 25 | * @param value Value of the element to be set 26 | */ 27 | void setValue(int index, T value); 28 | 29 | /** 30 | * Adds value to the vector. 31 | * 32 | * @param value Value of the element to be added 33 | */ 34 | boolean addValue(T value); 35 | 36 | /** 37 | * Returns value of the index-element 38 | * 39 | * @param index The position of the element (Index of the element) 40 | * @return Value of the element 41 | */ 42 | T getValue(int index); 43 | 44 | /** 45 | * Returns size of the vector 46 | * 47 | * @return Current size of the vector 48 | */ 49 | int getSize(); 50 | 51 | /** 52 | * This method detects duplicates in the vector 53 | * 54 | * @return true if the vector has duplicates, otherwise false 55 | */ 56 | boolean hasDuplicates(); 57 | 58 | /** 59 | * This method calculates the count of duplicates of a given value 60 | * 61 | * @return Number of the duplicates within the vector 62 | */ 63 | int countElements(T value); 64 | 65 | /** 66 | * This method detects if the victor contains a given value 67 | * 68 | * @return true if the vector contains the value, otherwise false 69 | */ 70 | boolean contains(T value); 71 | 72 | /** 73 | * This method detects if the vector's elements are equal. For example, this 74 | * method returns true for a vector (a, a, a) and false for a vector (a, b, a) 75 | * 76 | * @return True if the vector's elements are equal 77 | */ 78 | boolean isAllElementsEqual(); 79 | 80 | /** 81 | * Returns vector as a list of elements 82 | * 83 | * @return List of all elements 84 | */ 85 | List getVector(); 86 | 87 | /** 88 | * Clears the elements 89 | */ 90 | void clearVector(); 91 | } -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/composition/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the integer composition generators. 6 | 7 |

8 | A composition of an integer n is a way of writing n as the sum of a sequence 9 | of (strictly) positive integers. This class generates the composition if a 10 | positive integer value. 11 |

12 | A composition of an integer n is a way of writing n as the sum of a sequence 13 | of (strictly) positive integers. Two sequences that differ in the order of 14 | their terms define different compositions of their sum, while they are 15 | considered to define the same partition of that number. 16 |

17 | The sixteen compositions of 5 are: 18 |

    19 |
  1. 5 20 |
  2. 4+1 21 |
  3. 3+2 22 |
  4. 3+1+1 23 |
  5. 2+3 24 |
  6. 2+2+1 25 |
  7. 2+1+2 26 |
  8. 2+1+1+1 27 |
  9. 1+4 28 |
  10. 1+3+1 29 |
  11. 1+2+2 30 |
  12. 1+2+1+1 31 |
  13. 1+1+3 32 |
  14. 1+1+2+1 33 |
  15. 1+1+1+2 34 |
  16. 1+1+1+1+1. 35 |
36 |

37 | Compare this with the seven partitions of 5: 38 |

    39 |
  1. 5 40 |
  2. 4+1 41 |
  3. 3+2 42 |
  4. 3+1+1 43 |
  5. 2+2+1 44 |
  6. 2+1+1+1 45 |
  7. 1+1+1+1+1. 46 |
47 |

48 | Example. Generate compositions all possible integer compositions of 5. 49 |

50 |

51 | 52 |
53 |   // Create an instance of the integer composition generator to generate all possible compositions of 5
54 |   Generator<Integer> gen = CombinatoricsFactory.createCompositionGenerator(5);
55 | 
56 |   // Print the compositions
57 |   for (ICombinatoricsVector<Integer> p : gen) {
58 |      System.out.println(p);
59 |   }
60 | 
61 | 62 |
63 |

64 | And the result 65 |

66 |

67 | 68 |
69 |    CombinatoricsVector=([5], size=1)
70 |    CombinatoricsVector=([1, 4], size=2)
71 |    CombinatoricsVector=([2, 3], size=2)
72 |    CombinatoricsVector=([1, 1, 3], size=3)
73 |    CombinatoricsVector=([3, 2], size=2)
74 |    CombinatoricsVector=([1, 2, 2], size=3)
75 |    CombinatoricsVector=([2, 1, 2], size=3)
76 |    CombinatoricsVector=([1, 1, 1, 2], size=4)
77 |    CombinatoricsVector=([4, 1], size=2)
78 |    CombinatoricsVector=([1, 3, 1], size=3)
79 |    CombinatoricsVector=([2, 2, 1], size=3)
80 |    CombinatoricsVector=([1, 1, 2, 1], size=4)
81 |    CombinatoricsVector=([3, 1, 1], size=3)
82 |    CombinatoricsVector=([1, 2, 1, 1], size=4)
83 |    CombinatoricsVector=([2, 1, 1, 1], size=4)
84 |    CombinatoricsVector=([1, 1, 1, 1, 1], size=5)
85 | 
86 | 87 |
88 |

89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/util/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the utility classes and tools. 6 | 7 |

8 | It is possible to generate non-overlapping sublists of length n of a given list 9 |

10 | For example, if a list is (A, B, B, C), then the non-overlapping sublists of length 2 will be: 11 |

    12 |
  1. ( (A), (B, B, C) ) 13 |
  2. ( (B, B, C), (A) ) 14 |
  3. ( (B), (A, B, C) ) 15 |
  4. ( (A, B, C), (B) ) 16 |
  5. ( (A, B), (B, C) ) 17 |
  6. ( (B, C), (A, B) ) 18 |
  7. ( (B, B), (A, C) ) 19 |
  8. ( (A, C), (B, B) ) 20 |
  9. ( (A, B, B), (C) ) 21 |
  10. ( (C), (A, B, B) ) 22 |
23 |

24 | To do that you should use an instance of the complex combination generator 25 |

26 |

27 |
28 |   // create a vector (A, B, B, C)
29 |   ICombinatoricsVector<String> vector = Factory.createVector(new String[] { "A", "B", "B", "C" });
30 | 
31 |   // Create a complex-combination generator
32 |   Generator<ICombinatoricsVector<String>> gen = new ComplexCombinationGenerator<String>(vector, 2);
33 | 
34 |   // Iterate the combinations
35 |   for (ICombinatoricsVector<ICombinatoricsVector<String>> comb : gen) {
36 |      System.out.println(ComplexCombinationGenerator.convert2String(comb) + " - " + comb);
37 |   }
38 | 
39 | 40 |
41 |

42 | And the result 43 |

44 |

45 | 46 |
47 |  ([A],[B, B, C]) - CombinatoricsVector=([CombinatoricsVector=([A], size=1), CombinatoricsVector=([B, B, C], size=3)], size=2)
48 |  ([B, B, C],[A]) - CombinatoricsVector=([CombinatoricsVector=([B, B, C], size=3), CombinatoricsVector=([A], size=1)], size=2)
49 |  ([B],[A, B, C]) - CombinatoricsVector=([CombinatoricsVector=([B], size=1), CombinatoricsVector=([A, B, C], size=3)], size=2)
50 |  ([A, B, C],[B]) - CombinatoricsVector=([CombinatoricsVector=([A, B, C], size=3), CombinatoricsVector=([B], size=1)], size=2)
51 |  ([A, B],[B, C]) - CombinatoricsVector=([CombinatoricsVector=([A, B], size=2), CombinatoricsVector=([B, C], size=2)], size=2)
52 |  ([B, C],[A, B]) - CombinatoricsVector=([CombinatoricsVector=([B, C], size=2), CombinatoricsVector=([A, B], size=2)], size=2)
53 |  ([B, B],[A, C]) - CombinatoricsVector=([CombinatoricsVector=([B, B], size=2), CombinatoricsVector=([A, C], size=2)], size=2)
54 |  ([A, C],[B, B]) - CombinatoricsVector=([CombinatoricsVector=([A, C], size=2), CombinatoricsVector=([B, B], size=2)], size=2)
55 |  ([A, B, B],[C]) - CombinatoricsVector=([CombinatoricsVector=([A, B, B], size=3), CombinatoricsVector=([C], size=1)], size=2)
56 |  ([C],[A, B, B]) - CombinatoricsVector=([CombinatoricsVector=([C], size=1), CombinatoricsVector=([A, B, B], size=3)], size=2)
57 | 
58 | 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/IntegerGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Iterator; 9 | import java.util.List; 10 | 11 | /** 12 | * This is a special abstract class for all integer generators. 13 | * 14 | * There is a general pattern how to use the integer generators. 15 | * 16 | *
17 |  * // create an integer vector
18 |  * IntegerVector vector = new IntegerVector(new int[] { elements });
19 |  *
20 |  * // create a concrete integer generator
21 |  * IntegerGenerator generator = IntegerFactory.create < Concrete > Generator(vector);
22 |  *
23 |  * // Iterate the generated objects
24 |  * for (IntegerVector v : generator) {
25 |  * 	System.out.println(v);
26 |  * }
27 |  * 
28 | * 29 | * @author Dmytro Paukov 30 | * @version 2.0 31 | * @see IntegerVector 32 | * @see IntegerFactory 33 | * @see IGenerator 34 | */ 35 | public abstract class IntegerGenerator implements IGenerator { 36 | 37 | /** 38 | * Returns all generated vectors as a list 39 | * 40 | * @return List of all generated objects/vectors 41 | */ 42 | @Override 43 | public List generateAllObjects() { 44 | return generateFilteredObjects(null); 45 | } 46 | 47 | /** 48 | * Returns the generated vectors filtered by a filter 49 | * 50 | * @param filter The filter to be applied to the generated result 51 | * @return The list of the filtered vectors 52 | * @see IFilter 53 | */ 54 | @Override 55 | public List generateFilteredObjects( 56 | IFilter filter) { 57 | List list = new ArrayList(); 58 | long index = 0; 59 | for (IntegerVector vector : this) { 60 | if (filter == null || filter.accepted(index, vector)) { 61 | list.add(vector); 62 | } 63 | index++; 64 | } 65 | return list; 66 | } 67 | 68 | /** 69 | * Returns vectors as a list for specified range of indexes (from the 70 | * startIndex to stopIndex) 71 | * 72 | * @return List of the generated objects/vectors 73 | */ 74 | @Override 75 | public List generateObjectsRange(long startIndex, 76 | long stopIndex) { 77 | assert (startIndex <= stopIndex); 78 | List list = new ArrayList(); 79 | Iterator iterator = this.iterator(); 80 | int index = 1; 81 | while (iterator.hasNext()) { 82 | if (index >= startIndex && index <= stopIndex) { 83 | list.add(iterator.next()); 84 | } else if (index > stopIndex) { 85 | return list; 86 | } else { 87 | iterator.next(); 88 | } 89 | index++; 90 | } 91 | return list; 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/README.txt: -------------------------------------------------------------------------------- 1 | 2 | CombinatoricsLib - release notes 3 | by Dmytro Paukov 4 | 5 | CombinatoricsLib 2.4 (2021) 6 | 7 | 8 | ----------------------------------------------------------------- 9 | CombinatoricsLib 2.3 (Dec 2020) 10 | - Fixed combination number calculation (Issue #23). 11 | https://github.com/dpaukov/combinatoricslib/issues/23 12 | 13 | ----------------------------------------------------------------- 14 | CombinatoricsLib 2.2 (May 2018) 15 | - Added a method for calculating factorials using BigDecimal (Issue #10). 16 | - Added cartesian product generator. 17 | - Switched to Java 7. 18 | - Changed type of the input parameters for generateObjectsRange() from int to long (Issue #14) 19 | - Factory class renamed to CombinatoricsFactory (Issue #12) 20 | 21 | 22 | ----------------------------------------------------------------- 23 | CombinatoricsLib 2.1 (June 2014) 24 | - Fixed an issue with the Maven Central Repository (Issue 8) and 25 | incorrect name of the combinatoricsLib 26 | 27 | 28 | ----------------------------------------------------------------- 29 | CombinatoricsLib 2.0 (October 2012) 30 | - A new general interface ICombinatoricsVector has been introduced. 31 | All code has been re-factored to use this interface. 32 | - The permutation generator can produce the permutations even 33 | if the initial vector has duplicates. 34 | For example, library can generate all permutations of (1,1,2,2). 35 | - Factory class has been introduced to create all vectors and generators. 36 | - All generators implement the java interface Iterable, 37 | so they can be used in the "foreach" statement directly. 38 | - Filters have been introduced. All generated vectors can be easily filtered. 39 | - Representation of the combinatorics vectors as strings has been 40 | changed to format: "CombinatoricsVector=( [elements], size=value)". 41 | - Added the "complex" combination generator called ComplexCombinationGenerator 42 | and iterator to generate combinations in relation with 43 | permutations (list partitions). 44 | - Add several methods to detect if a vector contains duplicated elements. 45 | - SubSetGenerator has been updated to support duplicates in the original 46 | vector which represents the original set. To do that a new iterator 47 | called "SubListIterator" has been introduced. 48 | - Added a constructor to create a combinatorics vector from an array. 49 | - Added a factory class to make the library more flexible. 50 | 51 | ----------------------------------------------------------------- 52 | CombinatoricsLib 1.0 (December 2011) 53 | - Added combinations with repetitions 54 | - Added more unit tests 55 | 56 | 57 | ----------------------------------------------------------------- 58 | CombinatoricsLib 0.2 (July 2010) 59 | - Added compositions 60 | 61 | 62 | ----------------------------------------------------------------- 63 | CombinatoricsLib 0.1 (January 2010) 64 | - Permutations (with and without repetitions) 65 | - Partitions 66 | - Subsets 67 | - Simple combinations -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the subsets generators. 6 | 7 |

8 | A set A is a subset of a set B if A is "contained" inside B. A and B may 9 | coincide. The relationship of one set being a subset of another is called 10 | inclusion or sometimes containment. 11 |

12 | Examples: 13 |

    14 |
  • The set (1, 2) is a proper subset of (1, 2, 3). 15 |
  • Any set is a subset of itself, but not a proper subset. 16 |
  • The empty set, denoted by (), is also a subset of any given set X. 17 |
18 |

19 | All subsets of (1, 2, 3) are: 20 |

    21 |
  1. () 22 |
  2. (1) 23 |
  3. (2) 24 |
  4. (1, 2) 25 |
  5. (3) 26 |
  6. (1, 3) 27 |
  7. (2, 3) 28 |
  8. (1, 2, 3) 29 |
30 |

31 | And code which generates all subsets of (one, two, three) 32 |

33 |

34 |
 35 | // Create an initial vector/set
 36 | ICombinatoricsVector<String> initialSet = CombinatoricsFactory.createVector(new String[] {
 37 | 		"one", "two", "three" });
 38 | 
 39 | // Create an instance of the subset generator
 40 | Generator<String> gen = CombinatoricsFactory.createSubSetGenerator(initialSet);
 41 | 
 42 | // Print the subsets
 43 | for (ICombinatoricsVector<String> subSet : gen) {
 44 | 	System.out.println(subSet);
 45 | }
 46 | 
47 | 48 |
49 |

50 | And the result of all 8 possible subsets 51 |

52 |

53 | 54 |
 55 |  CombinatoricsVector=([], size=0)
 56 |  CombinatoricsVector=([one], size=1)
 57 |  CombinatoricsVector=([two], size=1)
 58 |  CombinatoricsVector=([one, two], size=2)
 59 |  CombinatoricsVector=([three], size=1)
 60 |  CombinatoricsVector=([one, three], size=2)
 61 |  CombinatoricsVector=([two, three], size=2)
 62 |  CombinatoricsVector=([one, two, three], size=3)
 63 | 
64 | 65 |
66 |

67 | Version 2.0 of the combinatoricslib supports sets with duplicates. For 68 | example, if the original vector contains duplicates like (a, b, a, c), then 69 | the result will contain 14 subsets (instead of 16): 70 |

71 | 72 |
 73 | ()
 74 | (a)
 75 | (b)
 76 | (a, b)
 77 | (a, a)
 78 | (b, a)
 79 | (a, b, a)
 80 | (c)
 81 | (a, c)
 82 | (b, c)
 83 | (a, b, c)
 84 | (a, a, c)
 85 | (b, a, c)
 86 | (a, b, a, c)
 87 | 
88 |
89 |

90 | If you still would like to treat the set with duplicates as not identical, 91 | you should create a generator and set the second parameter of the method 92 | CombinatoricsFactory.createSubSetGenerator() as false. In this 93 | case all 16 subsets will be generated. 94 |

95 | Note. If the initial vector contains duplicates then the method 96 | getNumberOfGeneratedObjects won't be able to return the number 97 | of the sub sets/lists. It will throw a runtime exception 98 |

99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/cartesian/CartesianProductTest.java: -------------------------------------------------------------------------------- 1 | package org.paukov.combinatorics.cartesian; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.paukov.combinatorics.CombinatoricsFactory.createCartesianProductGenerator; 5 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 6 | 7 | import java.util.Iterator; 8 | import java.util.List; 9 | import org.junit.Test; 10 | import org.paukov.combinatorics.CombinatoricsFactory; 11 | import org.paukov.combinatorics.Generator; 12 | import org.paukov.combinatorics.ICombinatoricsVector; 13 | 14 | /** 15 | * Created by dpaukov on 5/3/18. 16 | */ 17 | public class CartesianProductTest { 18 | 19 | @Test 20 | public void test_cartesian_product() { 21 | 22 | ICombinatoricsVector set01 = createVector("a", "b"); 23 | ICombinatoricsVector set02 = createVector("x", "y"); 24 | 25 | Generator cartesianProduct = createCartesianProductGenerator(set01, set02); 26 | 27 | Iterator> itr = cartesianProduct.iterator(); 28 | 29 | while (itr.hasNext()) { 30 | ICombinatoricsVector combination = itr.next(); 31 | System.out.println(combination); 32 | } 33 | 34 | List> list = cartesianProduct.generateAllObjects(); 35 | 36 | assertEquals(4, list.size()); 37 | assertEquals(4, cartesianProduct.getNumberOfGeneratedObjects()); 38 | 39 | assertEquals(list.get(0), createVector("a", "x")); 40 | assertEquals(list.get(1), createVector("a", "y")); 41 | assertEquals(list.get(2), createVector("b", "x")); 42 | assertEquals(list.get(3), createVector("b", "y")); 43 | } 44 | 45 | @Test 46 | public void test_cartesian_product_one_set_is_empty() { 47 | 48 | ICombinatoricsVector set01 = createVector("a", "b"); 49 | ICombinatoricsVector set02 = createVector(); 50 | 51 | Generator cartesianProduct = createCartesianProductGenerator(set01, set02); 52 | 53 | Iterator> itr = cartesianProduct.iterator(); 54 | 55 | while (itr.hasNext()) { 56 | ICombinatoricsVector combination = itr.next(); 57 | System.out.println(combination); 58 | } 59 | 60 | List> list = cartesianProduct.generateAllObjects(); 61 | 62 | assertEquals(0, list.size()); 63 | assertEquals(0, cartesianProduct.getNumberOfGeneratedObjects()); 64 | } 65 | 66 | @Test 67 | public void test_cartesian_product_empty() { 68 | 69 | Generator cartesianProduct = createCartesianProductGenerator( 70 | CombinatoricsFactory.createVector()); 71 | 72 | Iterator> itr = cartesianProduct.iterator(); 73 | 74 | while (itr.hasNext()) { 75 | ICombinatoricsVector combination = itr.next(); 76 | System.out.println(combination); 77 | } 78 | 79 | List> list = cartesianProduct.generateAllObjects(); 80 | 81 | assertEquals(0, list.size()); 82 | assertEquals(0, cartesianProduct.getNumberOfGeneratedObjects()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/IntegerSubListIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.subsets; 6 | 7 | import java.util.Iterator; 8 | import java.util.LinkedHashSet; 9 | import java.util.Set; 10 | import org.paukov.combinatorics.IntegerGenerator; 11 | import org.paukov.combinatorics.IntegerVector; 12 | 13 | /** 14 | * Iterator over the all sublists (with duplicates) of integer values. 15 | * 16 | * @author Dmytro Paukov 17 | * @version 2.0 18 | * @see IntegerVector 19 | * @see IntegerSubSetGenerator 20 | */ 21 | class IntegerSubListIterator implements Iterator { 22 | 23 | /** 24 | * Subset generator 25 | */ 26 | final IntegerGenerator _generator; 27 | 28 | /** 29 | * Sub set iterator 30 | */ 31 | final IntegerSubSetIterator _subSetsIterator; 32 | 33 | /** 34 | * Set of the result vectors (with duplicates) 35 | */ 36 | final Set _result = new LinkedHashSet<>(); 37 | 38 | /** 39 | * Current sublist 40 | */ 41 | IntegerVector _currentSubList = null; 42 | 43 | /** 44 | * Index of the current sub-list 45 | */ 46 | long _currentIndex = 0; 47 | 48 | /** 49 | * Iterator over the result vectors 50 | */ 51 | Iterator _resultIterator = null; 52 | 53 | /** 54 | * Constructor 55 | * 56 | * @param generator The subset generator 57 | */ 58 | IntegerSubListIterator(IntegerGenerator generator) { 59 | _generator = generator; 60 | _subSetsIterator = new IntegerSubSetIterator(generator); 61 | init(); 62 | } 63 | 64 | /** 65 | * Initializes the iterator 66 | * 67 | * @see org.paukov.combinatorics.iterator.Iterator#first() 68 | */ 69 | private void init() { 70 | _currentIndex = 0; 71 | while (_subSetsIterator.hasNext()) { 72 | IntegerVector subVector = _subSetsIterator.next(); 73 | _result.add(subVector); 74 | } 75 | _resultIterator = _result.iterator(); 76 | } 77 | 78 | /** 79 | * Returns true if iteration is done, otherwise false 80 | * 81 | * @see Iterator#hasNext() 82 | */ 83 | @Override 84 | public boolean hasNext() { 85 | return _resultIterator.hasNext(); 86 | } 87 | 88 | /** 89 | * Returns the next sublist if it is available 90 | * 91 | * @see Iterator#next() 92 | */ 93 | @Override 94 | public IntegerVector next() { 95 | _currentIndex++; 96 | _currentSubList = _resultIterator.next(); 97 | return _currentSubList; 98 | } 99 | 100 | @Override 101 | public void remove() { 102 | throw new UnsupportedOperationException(); 103 | } 104 | 105 | /** 106 | * Returns a string representation 107 | * 108 | * @see java.lang.Object#toString() 109 | */ 110 | @Override 111 | public String toString() { 112 | return "IntegerSubListIterator=[#" + _currentIndex + ", " 113 | + _currentSubList + "]"; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/SubListIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.subsets; 6 | 7 | import java.util.Iterator; 8 | import java.util.LinkedHashSet; 9 | import java.util.Set; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | 13 | /** 14 | * Iterator over the all sublists (with duplicates) 15 | * 16 | * @param Type of the elements in the lists 17 | * @author Dmytro Paukov 18 | * @version 2.0 19 | * @see ICombinatoricsVector 20 | * @see SubSetGenerator 21 | */ 22 | class SubListIterator implements Iterator> { 23 | 24 | /** 25 | * Subset generator 26 | */ 27 | final Generator _generator; 28 | 29 | /** 30 | * Sub set iterator 31 | */ 32 | final SubSetIterator _subSetsIterator; 33 | 34 | /** 35 | * Set of the result vectors (with duplicates) 36 | */ 37 | final Set> _result = new LinkedHashSet<>(); 38 | 39 | /** 40 | * Current sublist 41 | */ 42 | ICombinatoricsVector _currentSubList = null; 43 | 44 | /** 45 | * Index of the current sub-list 46 | */ 47 | long _currentIndex = 0; 48 | 49 | /** 50 | * Iterator over the result vectors 51 | */ 52 | Iterator> _resultIterator = null; 53 | 54 | /** 55 | * Constructor 56 | * 57 | * @param generator The subset generator 58 | */ 59 | SubListIterator(Generator generator) { 60 | _generator = generator; 61 | _subSetsIterator = new SubSetIterator(generator); 62 | init(); 63 | } 64 | 65 | /** 66 | * Initializes the iterator 67 | * 68 | * @see org.paukov.combinatorics.iterator.Iterator#first() 69 | */ 70 | private void init() { 71 | _currentIndex = 0; 72 | while (_subSetsIterator.hasNext()) { 73 | ICombinatoricsVector subVector = _subSetsIterator.next(); 74 | _result.add(subVector); 75 | } 76 | _resultIterator = _result.iterator(); 77 | } 78 | 79 | /** 80 | * Returns true if iteration is done, otherwise false 81 | * 82 | * @see Iterator#hasNext() 83 | */ 84 | @Override 85 | public boolean hasNext() { 86 | return _resultIterator.hasNext(); 87 | } 88 | 89 | /** 90 | * Returns the next sublist if it is available 91 | * 92 | * @see Iterator#next() 93 | */ 94 | @Override 95 | public ICombinatoricsVector next() { 96 | _currentIndex++; 97 | _currentSubList = _resultIterator.next(); 98 | return _currentSubList; 99 | } 100 | 101 | @Override 102 | public void remove() { 103 | throw new UnsupportedOperationException(); 104 | } 105 | 106 | /** 107 | * Returns a string representation 108 | * 109 | * @see java.lang.Object#toString() 110 | */ 111 | @Override 112 | public String toString() { 113 | return "SubListIterator=[#" + _currentIndex + ", " + _currentSubList + "]"; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/permutations/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This package contains the generators for the permutations with and without repetitions. 6 | 7 | 8 |

Simple permutations

9 | A permutation is an ordering of a set in the context of all possible orderings. For example, the set 10 | containing the first three digits, 123, has 11 | six permutations: 123, 132, 213, 231, 312, and 321. 12 |

13 | This is an example of the permutations of 3 string items (apple, orange, cherry): 14 |

15 |

16 |
17 | // Create the initial vector of 3 elements (apple, orange, cherry)
18 | ICombinatoricsVector<String> originalVector = CombinatoricsFactory.createVector(new String[] { "apple", "orange", "cherry" });
19 | 
20 | // Create the permutation generator by calling the appropriate method of the Factory class
21 | Generator<String> gen = CombinatoricsFactory.createPermutationGenerator(originalVector);
22 | 
23 | // Print the result
24 | for (ICombinatoricsVector<String> perm : gen)
25 | 	System.out.println(perm);
26 | 
27 |
28 | 29 |

30 | And the result 31 |

32 |

33 |
34 |   CombinatoricsVector=([apple, orange, cherry], size=3)
35 |   CombinatoricsVector=([apple, cherry, orange], size=3)
36 |   CombinatoricsVector=([cherry, apple, orange], size=3)
37 |   CombinatoricsVector=([cherry, orange, apple], size=3)
38 |   CombinatoricsVector=([orange, cherry, apple], size=3)
39 |   CombinatoricsVector=([orange, apple, cherry], size=3)
40 | 
41 |
42 |

43 | 44 |

Permutations with repetitions

45 |

46 | The permutation may have more elements than slots. For example, the three 47 | possible permutation of 12 in three slots are: 111, 211, 121, 221, 112, 212, 48 | 122, and 222. 49 |

50 | Let's generate all possible permutations with repetitions of 3 elements from 51 | the set of apple and orange: 52 |

53 |

54 |
55 | // Create the initial vector of 2 elements (apple, orange)
56 | ICombinatoricsVector<String> originalVector = Factory.createVector(new String[] { "apple", "orange" });
57 | 
58 | // Create the generator by calling the appropriate method in the Factory class. 
59 | // Set the second parameter as 3, since we will generate 3-elemets permutations
60 | Generator<String> gen = Factory.createPermutationWithRepetitionGenerator(originalVector, 3);
61 | 
62 | // Print the result
63 | for (ICombinatoricsVector<String> perm : gen)
64 |    System.out.println( perm );
65 | 
66 |
67 |

68 | And the result 69 |

70 |

71 |
72 |   CombinatoricsVector=([apple, apple, apple], size=3)
73 |   CombinatoricsVector=([orange, apple, apple], size=3)
74 |   CombinatoricsVector=([apple, orange, apple], size=3)
75 |   CombinatoricsVector=([orange, orange, apple], size=3)
76 |   CombinatoricsVector=([apple, apple, orange], size=3)
77 |   CombinatoricsVector=([orange, apple, orange], size=3)
78 |   CombinatoricsVector=([apple, orange, orange], size=3)
79 |   CombinatoricsVector=([orange, orange, orange], size=3)
80 | 
81 |
82 |

83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/SubSetIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.subsets; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | 13 | /** 14 | * Iterator over the all subsets 15 | * 16 | * @param Type of the elements of the subsets 17 | * @author Dmytro Paukov 18 | * @version 2.0 19 | * @see ICombinatoricsVector 20 | * @see SubSetGenerator 21 | */ 22 | class SubSetIterator implements Iterator> { 23 | 24 | /** 25 | * Subset generator 26 | */ 27 | final Generator _generator; 28 | /** 29 | * Size of the subset 30 | */ 31 | final int _length; 32 | /** 33 | * Current subset 34 | */ 35 | ICombinatoricsVector _currentSubSet = null; 36 | /** 37 | * Index of the current subset 38 | */ 39 | long _currentIndex = 0; 40 | /** 41 | * internal bit vector, representing the subset 42 | */ 43 | private int[] _bitVector = null; 44 | 45 | /** 46 | * Constructor 47 | * 48 | * @param generator The subset generator 49 | */ 50 | SubSetIterator(Generator generator) { 51 | _generator = generator; 52 | _length = generator.getOriginalVector().getSize(); 53 | _currentSubSet = createVector(); 54 | _bitVector = new int[_length + 2]; 55 | init(); 56 | } 57 | 58 | /** 59 | * initialize the iterator 60 | * 61 | * @see org.paukov.combinatorics.iterator.Iterator#first() 62 | */ 63 | private void init() { 64 | _currentIndex = 0; 65 | for (int i = 0; i <= _length + 1; i++) { 66 | _bitVector[i] = 0; 67 | } 68 | 69 | } 70 | 71 | /** 72 | * Returns true if iteration is done, otherwise false 73 | * 74 | * @see Iterator#hasNext() 75 | */ 76 | @Override 77 | public boolean hasNext() { 78 | return _bitVector[_length + 1] != 1; 79 | } 80 | 81 | /** 82 | * Returns the next subset if it is available 83 | * 84 | * @see Iterator#next() 85 | */ 86 | @Override 87 | public ICombinatoricsVector next() { 88 | _currentIndex++; 89 | _currentSubSet.clearVector(); 90 | for (int index = 1; index <= _length; index++) { 91 | if (_bitVector[index] == 1) { 92 | T value = _generator.getOriginalVector().getValue(index - 1); 93 | _currentSubSet.addValue(value); 94 | } 95 | } 96 | int i = 1; 97 | while (_bitVector[i] == 1) { 98 | _bitVector[i] = 0; 99 | i++; 100 | } 101 | _bitVector[i] = 1; 102 | 103 | return createVector(_currentSubSet); 104 | } 105 | 106 | @Override 107 | public void remove() { 108 | throw new UnsupportedOperationException(); 109 | } 110 | 111 | /** 112 | * Convert 113 | * 114 | * @see java.lang.Object#toString() 115 | */ 116 | @Override 117 | public String toString() { 118 | return "SubSetIterator=[#" + _currentIndex + ", " + _currentSubSet + "]"; 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/IntegerSubSetIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.subsets; 6 | 7 | import java.util.Iterator; 8 | import org.paukov.combinatorics.IntegerFactory; 9 | import org.paukov.combinatorics.IntegerGenerator; 10 | import org.paukov.combinatorics.IntegerVector; 11 | 12 | /** 13 | * Iterator over the all subsets 14 | * 15 | * @author Dmytro Paukov 16 | * @version 2.0 17 | * @see IntegerVector 18 | * @see IntegerSubSetGenerator 19 | */ 20 | class IntegerSubSetIterator implements Iterator { 21 | 22 | /** 23 | * Subset generator 24 | */ 25 | final IntegerGenerator _generator; 26 | 27 | /** 28 | * Size of the subset 29 | */ 30 | final int _length; 31 | 32 | /** 33 | * Current subset 34 | */ 35 | IntegerVector _currentSubSet = null; 36 | 37 | /** 38 | * Index of the current subset 39 | */ 40 | long _currentIndex = 0; 41 | 42 | /** 43 | * internal bit vector, representing the subset 44 | */ 45 | private int[] _bitVector = null; 46 | 47 | /** 48 | * Constructor 49 | * 50 | * @param generator The subset generator 51 | */ 52 | IntegerSubSetIterator(IntegerGenerator generator) { 53 | _generator = generator; 54 | _length = generator.getOriginalVector().getSize(); 55 | _currentSubSet = IntegerFactory.createIntegerVector(0); 56 | _bitVector = new int[_length + 2]; 57 | init(); 58 | } 59 | 60 | /** 61 | * initialize the iterator 62 | * 63 | * @see org.paukov.combinatorics.iterator.Iterator#first() 64 | */ 65 | private void init() { 66 | _currentIndex = 0; 67 | for (int i = 0; i <= _length + 1; i++) { 68 | _bitVector[i] = 0; 69 | } 70 | 71 | } 72 | 73 | /** 74 | * Returns true if iteration is done, otherwise false 75 | * 76 | * @see Iterator#hasNext() 77 | */ 78 | @Override 79 | public boolean hasNext() { 80 | return _bitVector[_length + 1] != 1; 81 | } 82 | 83 | /** 84 | * Returns the next subset if it is available 85 | * 86 | * @see Iterator#next() 87 | */ 88 | @Override 89 | public IntegerVector next() { 90 | _currentIndex++; 91 | 92 | int[] temp = new int[_length]; 93 | int j = 0; 94 | for (int index = 1; index <= _length; index++) { 95 | if (_bitVector[index] == 1) { 96 | int value = _generator.getOriginalVector().getValue(index - 1); 97 | temp[j++] = value; 98 | } 99 | } 100 | _currentSubSet = IntegerFactory.createIntegerVector(temp, j); 101 | 102 | int i = 1; 103 | while (_bitVector[i] == 1) { 104 | _bitVector[i++] = 0; 105 | } 106 | _bitVector[i] = 1; 107 | return _currentSubSet; 108 | } 109 | 110 | @Override 111 | public void remove() { 112 | throw new UnsupportedOperationException(); 113 | } 114 | 115 | /** 116 | * Convert 117 | * 118 | * @see java.lang.Object#toString() 119 | */ 120 | @Override 121 | public String toString() { 122 | return "IntegerSubSetIterator=[#" + _currentIndex + ", " + _currentSubSet + "]"; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/cartesian/CartesianProductIterator.java: -------------------------------------------------------------------------------- 1 | package org.paukov.combinatorics.cartesian; 2 | 3 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 4 | 5 | import java.util.Iterator; 6 | import org.paukov.combinatorics.ICombinatoricsVector; 7 | 8 | /** 9 | * Iterator for the cartesian product generator 10 | * 11 | * @param Type of the elements in the cartesian product 12 | * @author Julius Iglesia, Dmytro Paukov 13 | * @version 2.2 14 | * @see CartesianProductGenerator 15 | */ 16 | class CartesianProductIterator implements 17 | Iterator> { 18 | 19 | private final int vectorSize; 20 | private final int[] indices; 21 | private ICombinatoricsVector> vector; 22 | private int nextIndex; 23 | private ICombinatoricsVector current; 24 | 25 | private int index = 0; 26 | 27 | private boolean hasEmptyList = false; 28 | 29 | CartesianProductIterator(CartesianProductGenerator generator) { 30 | vector = generator.originalVector; 31 | vectorSize = generator.originalVector.getSize(); 32 | 33 | // start from the last index 34 | nextIndex = vectorSize - 1; 35 | 36 | // for tracking the indices of the product 37 | indices = new int[this.vectorSize]; 38 | 39 | // for the tracking the lengths of the lists 40 | for (int i = 0; i < vectorSize; i++) { 41 | hasEmptyList = hasEmptyList || vector.getValue(i).getSize() == 0; 42 | } 43 | } 44 | 45 | /** 46 | * Returns true if all cartesian products were iterated, otherwise false 47 | */ 48 | @Override 49 | public boolean hasNext() { 50 | return !hasEmptyList && nextIndex >= 0; 51 | } 52 | 53 | /** 54 | * Moves to the next Cartesian product 55 | */ 56 | @Override 57 | public ICombinatoricsVector next() { 58 | if (index == 0) { 59 | return generateCartesianProduct(); 60 | } 61 | 62 | if (nextIndex < 0) { 63 | throw new RuntimeException("No more cartesian product."); 64 | } 65 | 66 | // Move to the next element 67 | indices[nextIndex]++; 68 | 69 | for (int i = nextIndex + 1; i < vectorSize; i++) { 70 | indices[i] = 0; 71 | } 72 | 73 | return generateCartesianProduct(); 74 | } 75 | 76 | @Override 77 | public void remove() { 78 | throw new UnsupportedOperationException(); 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "CartesianProductIterator=[#" + index + ", " + current + "]"; 84 | } 85 | 86 | private ICombinatoricsVector generateCartesianProduct() { 87 | current = createVector(); 88 | for (int i = 0; i < vectorSize; i++) { 89 | current.addValue(vector.getValue(i).getValue(indices[i])); 90 | } 91 | 92 | // After generating the current, check if has still next cartesian product, 93 | // this will be used by #hasNext function 94 | checkIfHasNextCartesianProduct(); 95 | index++; 96 | 97 | return current; 98 | } 99 | 100 | private void checkIfHasNextCartesianProduct() { 101 | // Check if has still cartesian product by finding an array that has more elements left 102 | nextIndex = vectorSize - 1; 103 | while (nextIndex >= 0 && 104 | indices[nextIndex] + 1 >= vector.getValue(nextIndex).getSize()) { 105 | nextIndex--; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/combination/simple/SimpleCombinationGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.combination.simple; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | import org.paukov.combinatorics.util.Util; 13 | 14 | /** 15 | * This generator generates simple combinations from specified core set by 16 | * specified length. Core set and length are specified in the constructor of 17 | * generator 18 | *

19 | * A simple k-combination of a finite set S is a subset of k distinct elements 20 | * of S. Specifying a subset does not arrange them in a particular order. As an 21 | * example, a poker hand can be described as a 5-combination of cards from a 22 | * 52-card deck: the 5 cards of the hand are all distinct, and the order of the 23 | * cards in the hand does not matter. 24 | *

25 | * Example. Generate 3-combination of the set (red, black, white, green, blue). 26 | *

27 | *

28 | * 29 | *
 30 |  *
 31 |  * // Create the initial vector
 32 |  * ICombinatoricsVector<String> initialVector = CombinatoricsFactory.createVector(
 33 |  *   new String[]{
 34 |  *     "red", "black", "white", "green", "blue" });
 35 |  *
 36 |  * // Create a simple combination generator to generate 3-combinations of the
 37 |  * // initial vector
 38 |  * Generator<String> gen = CombinatoricsFactory.createSimpleCombinationGenerator(
 39 |  *   initialVector, 3);
 40 |  *
 41 |  * // Print all possible combinations
 42 |  * for (ICombinatoricsVector<String> combination : gen) {
 43 |  * 	System.out.println(combination);
 44 |  * }
 45 |  * 
46 | * 47 | *
48 | *

49 | * 50 | * @param Type of elements in the combination 51 | * @author Dmytro Paukov 52 | * @version 2.0 53 | * @see SimpleCombinationIterator 54 | */ 55 | public class SimpleCombinationGenerator extends Generator { 56 | 57 | protected final ICombinatoricsVector _originalVector; 58 | protected final int _combinationLength; 59 | 60 | /** 61 | * Constructor 62 | * 63 | * @param originalVector Original vector which is used for generating the combination 64 | * @param combinationsLength Length of the combinations 65 | */ 66 | public SimpleCombinationGenerator(ICombinatoricsVector originalVector, 67 | int combinationsLength) { 68 | _originalVector = createVector(originalVector); 69 | _combinationLength = combinationsLength; 70 | } 71 | 72 | /** 73 | * Returns the original vector/set 74 | * 75 | * @return Returns the _originalVector. 76 | */ 77 | public ICombinatoricsVector getOriginalVector() { 78 | return _originalVector; 79 | } 80 | 81 | /** 82 | * Returns the length of the combinations 83 | * 84 | * @return Returns the _combinationLength. 85 | */ 86 | public int getCombinationLength() { 87 | return _combinationLength; 88 | } 89 | 90 | /** 91 | * Returns the number of the generated combinations 92 | */ 93 | public long getNumberOfGeneratedObjects() { 94 | return Util.combination(_originalVector.getSize(), _combinationLength); 95 | } 96 | 97 | /** 98 | * Creates an iterator of the simple combinations (without repetitions) 99 | */ 100 | @Override 101 | public Iterator> iterator() { 102 | return new SimpleCombinationIterator<>(this); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/composition/IntegerCompositionGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.composition; 6 | 7 | import static org.paukov.combinatorics.IntegerFactory.createIntegerVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.IntegerGenerator; 11 | import org.paukov.combinatorics.IntegerVector; 12 | import org.paukov.combinatorics.util.Util; 13 | 14 | /** 15 | * A composition of an integer n is a way of writing n as the sum of a sequence of (strictly) 16 | * positive integers. This class generates the composition if a positive integer value. 17 | * 18 | * A composition of an integer n is a way of writing n as the sum of a sequence of (strictly) 19 | * positive integers. Two sequences that differ in the order of their terms define different 20 | * compositions of their sum, while they are considered to define the same partition of that 21 | * number. 22 | * 23 | * The sixteen compositions of 5 are: 5, 4+1, 3+2, 3+1+1, 2+3, 2+2+1, 2+1+2, 2+1+1+1, 1+4, 1+3+1, 24 | * 1+2+2, 1+2+1+1, 1+1+3, 1+1+2+1, 1+1+1+2, 1+1+1+1+1. 25 | * 26 | * Compare this with the seven partitions of 5: 5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1. 27 | * 28 | * Example. Generate compositions all possible integer compositions of 5. 29 | * 30 | *

 31 |  *   // Create an instance of the integer composition generator to generate all possible
 32 |  * compositions of 5
 33 |  *   IntegerGenerator gen = IntegerFactory.createIntegerCompositionGenerator(5);
 34 |  *
 35 |  *   // Print the compositions
 36 |  *   for (IntegerVector p : gen) {
 37 |  *      System.out.println(p);
 38 |  *   }
 39 |  * 
40 | * 41 | * And the result 42 | * 43 | *
 44 |  *    IntegerVector=([5], size=1)
 45 |  *    IntegerVector=([1, 4], size=2)
 46 |  *    IntegerVector=([2, 3], size=2)
 47 |  *    IntegerVector=([1, 1, 3], size=3)
 48 |  *    IntegerVector=([3, 2], size=2)
 49 |  *    IntegerVector=([1, 2, 2], size=3)
 50 |  *    IntegerVector=([2, 1, 2], size=3)
 51 |  *    IntegerVector=([1, 1, 1, 2], size=4)
 52 |  *    IntegerVector=([4, 1], size=2)
 53 |  *    IntegerVector=([1, 3, 1], size=3)
 54 |  *    IntegerVector=([2, 2, 1], size=3)
 55 |  *    IntegerVector=([1, 1, 2, 1], size=4)
 56 |  *    IntegerVector=([3, 1, 1], size=3)
 57 |  *    IntegerVector=([1, 2, 1, 1], size=4)
 58 |  *    IntegerVector=([2, 1, 1, 1], size=4)
 59 |  *    IntegerVector=([1, 1, 1, 1, 1], size=5)
 60 |  * 
61 | * 62 | * @author Dmytro Paukov 63 | * @version 2.0 64 | * @see IntegerCompositionIterator 65 | */ 66 | public class IntegerCompositionGenerator extends IntegerGenerator { 67 | 68 | public static final int MAXN = 100; 69 | 70 | protected final Integer _initialValue; 71 | 72 | /** 73 | * Constructor 74 | * 75 | * @param n A positive integer value 76 | */ 77 | public IntegerCompositionGenerator(Integer n) { 78 | super(); 79 | this._initialValue = n; 80 | } 81 | 82 | /** 83 | * Returns the value which is used for generating the compositions. This value is 84 | * returned as an element of the single value vector. 85 | */ 86 | @Override 87 | public IntegerVector getOriginalVector() { 88 | return createIntegerVector(new int[]{_initialValue}); 89 | } 90 | 91 | /** 92 | * Returns number of the compositions 93 | */ 94 | @Override 95 | public long getNumberOfGeneratedObjects() { 96 | return Util.pow2(_initialValue - 1); 97 | } 98 | 99 | /** 100 | * Creates the iterator over all compositions 101 | */ 102 | @Override 103 | public Iterator iterator() { 104 | return new IntegerCompositionIterator(this); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/Generator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Iterator; 9 | import java.util.List; 10 | 11 | /** 12 | * Abstract base class for all generic generators of the library. 13 | * 14 | * This is a library written on Java to resolve some combinatorics issues such 15 | * as generating combinatorial objects (permutations, partitions, compositions, 16 | * subsets, combinations and etc). 17 | * 18 | * Type of the items should be specified as a parameter of generators and vectors. 19 | * 20 | * There is a general pattern how to use the generators: 21 | *
 22 |  * // create the initial vector or set
 23 |  * ICombinatoricsVector<T> vector = CombinatoricsFactory.createVector(new <T>[]{ elements } );
 24 |  *
 25 |  * // create a concrete generator
 26 |  * Generator<T> generator = CombinatoricsFactory.create<Concrete>Generator(vector);
 27 |  *
 28 |  * // iterate the generated objects
 29 |  * for (ICombinatoricsVector<T> v : generator) {
 30 |  * 	System.out.println( v );
 31 |  * }
 32 |  * 
33 | * 34 | * @param Type of the elements in the generated vectors. 35 | * @author Dmytro Paukov 36 | * @version 2.0 37 | * @see ICombinatoricsVector 38 | * @see Iterator 39 | * @see CombinatoricsFactory 40 | */ 41 | public abstract class Generator implements 42 | IGenerator> { 43 | 44 | /** 45 | * Creates an iterator for enumerating all generated objects/vectors 46 | * 47 | * @return The iterator over the generated objects/vectors 48 | * @deprecated This method will removed in the near future. Use the method iterator() 49 | * instead of this method 50 | */ 51 | @Deprecated 52 | public Iterator> createIterator() { 53 | return iterator(); 54 | } 55 | 56 | /** 57 | * Returns all generated vectors as a list 58 | * 59 | * @return List of all generated objects/vectors 60 | */ 61 | public List> generateAllObjects() { 62 | return generateFilteredObjects(null); 63 | } 64 | 65 | /** 66 | * Returns the generated vectors filtered by a filter 67 | * 68 | * @param filter The filter to be applied to the generated result 69 | * @return The list of the filtered vectors 70 | */ 71 | public List> generateFilteredObjects( 72 | IFilter> filter) { 73 | List> list = new ArrayList<>(); 74 | long index = 0; 75 | for (ICombinatoricsVector vector : this) { 76 | if (filter == null || filter.accepted(index, vector)) { 77 | list.add(vector); 78 | } 79 | index++; 80 | } 81 | return list; 82 | } 83 | 84 | /** 85 | * Returns vectors as a list for specified range of indexes (from the 86 | * startIndex to stopIndex) 87 | * 88 | * @return List of the generated objects/vectors 89 | */ 90 | public List> generateObjectsRange(long startIndex, 91 | long stopIndex) { 92 | assert (startIndex <= stopIndex); 93 | List> list = new ArrayList<>(); 94 | Iterator> iterator = this.iterator(); 95 | long index = 1; 96 | while (iterator.hasNext()) { 97 | if (index >= startIndex && index <= stopIndex) { 98 | list.add(iterator.next()); 99 | } else if (index > stopIndex) { 100 | return list; 101 | } else { 102 | iterator.next(); 103 | } 104 | index++; 105 | } 106 | return list; 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/permutations/PermutationIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.permutations; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | 13 | /** 14 | * Iterator for the permutation generator 15 | * 16 | * @param Type of elements in the permutations 17 | * @author Dmytro Paukov 18 | * @version 2.0 19 | * @see ICombinatoricsVector 20 | * @see PermutationGenerator 21 | */ 22 | class PermutationIterator implements Iterator> { 23 | 24 | /** 25 | * Generator 26 | */ 27 | final Generator _generator; 28 | 29 | /** 30 | * Number of elements in the permutations 31 | */ 32 | final int _length; 33 | 34 | /** 35 | * Current permutation 36 | */ 37 | ICombinatoricsVector _currentPermutation; 38 | 39 | /** 40 | * Current index of current permutation 41 | */ 42 | long _currentIndex = 0; 43 | 44 | /** 45 | * Internal data 46 | */ 47 | private int[] _pZ = null; 48 | private int[] _pP = null; 49 | private int[] _pD = null; 50 | private int m = 0; 51 | private int w = 0; 52 | private int pm = 0; 53 | private int dm = 0; 54 | private int zpm = 0; 55 | 56 | /** 57 | * Constructor 58 | * 59 | * @param generator Permutation generator 60 | */ 61 | PermutationIterator(Generator generator) { 62 | _generator = generator; 63 | _length = generator.getOriginalVector().getSize(); 64 | _currentPermutation = createVector(generator.getOriginalVector()); 65 | _pZ = new int[_length + 2]; 66 | _pP = new int[_length + 2]; 67 | _pD = new int[_length + 2]; 68 | init(); 69 | } 70 | 71 | /** 72 | * Initialize the iteration process 73 | */ 74 | private void init() { 75 | _currentIndex = 0; 76 | 77 | m = 0; 78 | w = 0; 79 | pm = 0; 80 | dm = 0; 81 | zpm = 0; 82 | 83 | for (int i = 1; i <= _length; i++) { 84 | _pP[i] = i; 85 | _pZ[i] = i; 86 | _pD[i] = -1; 87 | } 88 | _pD[1] = 0; 89 | _pZ[_length + 1] = m = _length + 1; 90 | _pZ[0] = _pZ[_length + 1]; 91 | 92 | } 93 | 94 | 95 | /** 96 | * Return true if the iteration process is finished 97 | */ 98 | @Override 99 | public boolean hasNext() { 100 | return m != 1; 101 | } 102 | 103 | /** 104 | * Moves to the next permutation 105 | */ 106 | @Override 107 | public ICombinatoricsVector next() { 108 | 109 | for (int i = 1; i <= _length; i++) { 110 | int index = _pZ[i] - 1; 111 | _currentPermutation.setValue(i - 1, _generator.getOriginalVector() 112 | .getValue(index)); 113 | } 114 | m = _length; 115 | while (_pZ[_pP[m] + _pD[m]] > m) { 116 | _pD[m] = -_pD[m]; 117 | m--; 118 | } 119 | pm = _pP[m]; 120 | dm = pm + _pD[m]; 121 | w = _pZ[pm]; 122 | _pZ[pm] = _pZ[dm]; 123 | _pZ[dm] = w; 124 | zpm = _pZ[pm]; 125 | w = _pP[zpm]; 126 | _pP[zpm] = pm; 127 | _pP[m] = w; 128 | _currentIndex++; 129 | 130 | return createVector(_currentPermutation); 131 | } 132 | 133 | @Override 134 | public void remove() { 135 | throw new UnsupportedOperationException(); 136 | } 137 | 138 | /** 139 | * Returns the current permutation as a string 140 | * 141 | * @see java.lang.Object#toString() 142 | */ 143 | @Override 144 | public String toString() { 145 | return "PermutationIterator=[#" + _currentIndex + ", " + _currentPermutation + "]"; 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/composition/IntegerCompositionIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.composition; 6 | 7 | import java.util.Iterator; 8 | import org.paukov.combinatorics.IntegerFactory; 9 | import org.paukov.combinatorics.IntegerGenerator; 10 | import org.paukov.combinatorics.IntegerVector; 11 | 12 | /** 13 | * Iterator for enumerating all possible compositions. 14 | * 15 | * @author Dmytro Paukov 16 | * @version 2.0 17 | * @see IntegerVector 18 | * @see IntegerCompositionGenerator 19 | */ 20 | class IntegerCompositionIterator implements Iterator { 21 | 22 | /** 23 | * Generator 24 | */ 25 | final IntegerCompositionGenerator _generator; 26 | 27 | /** 28 | * Subset generator 29 | */ 30 | final IntegerGenerator _subsetGenerator; 31 | 32 | /** 33 | * Subset iterator 34 | */ 35 | final Iterator _subsetIterator; 36 | 37 | /** 38 | * Current composition 39 | */ 40 | IntegerVector _currentComposition = null; 41 | 42 | /** 43 | * Current index of the weak composition 44 | */ 45 | long _currentIndex = 0; 46 | 47 | /** 48 | * Current subset 49 | */ 50 | IntegerVector _currentSubset = null; 51 | 52 | /** 53 | * Constructor of the iterator 54 | * 55 | * @param generator The composition generator 56 | */ 57 | IntegerCompositionIterator(IntegerCompositionGenerator generator) { 58 | super(); 59 | _generator = generator; 60 | 61 | int coreSize = 0; 62 | 63 | if (this._generator._initialValue > 0) { 64 | coreSize = this._generator._initialValue - 1; 65 | } 66 | 67 | IntegerVector coreSet = IntegerFactory.createIntegerVector(coreSize); 68 | 69 | for (int i = 1; i < this._generator._initialValue; i++) { 70 | coreSet.setValue(i - 1, i); 71 | } 72 | 73 | _subsetGenerator = IntegerFactory.createIntegerSubSetGenerator(coreSet); 74 | 75 | _subsetIterator = _subsetGenerator.iterator(); 76 | } 77 | 78 | /** 79 | * Returns the next composition 80 | */ 81 | @Override 82 | public IntegerVector next() { 83 | _currentIndex++; 84 | _currentSubset = this._subsetIterator.next(); 85 | return getCurrentItem(); 86 | } 87 | 88 | /** 89 | * Returns true when all composition are iterated 90 | */ 91 | @Override 92 | public boolean hasNext() { 93 | return this._subsetIterator.hasNext(); 94 | } 95 | 96 | /** 97 | * Returns current composition 98 | */ 99 | private IntegerVector getCurrentItem() { 100 | 101 | int[] vector = _currentSubset.getVector(); 102 | _currentComposition = IntegerFactory 103 | .createIntegerVector(vector.length + 1); 104 | 105 | int currentValueSubSet = 0; 106 | int valueCompositionElement = 0; 107 | 108 | for (int i = 0; i < vector.length; i++) { 109 | int currentSubsetElement = vector[i]; 110 | valueCompositionElement = currentSubsetElement - currentValueSubSet; 111 | _currentComposition.setValue(i, valueCompositionElement); 112 | 113 | currentValueSubSet = currentSubsetElement; 114 | } 115 | _currentComposition.setValue(vector.length, _generator._initialValue 116 | - currentValueSubSet); 117 | 118 | return _currentComposition; 119 | } 120 | 121 | @Override 122 | public void remove() { 123 | throw new UnsupportedOperationException(); 124 | } 125 | 126 | /** 127 | * Returns composition as a string 128 | * 129 | * @see java.lang.Object#toString() 130 | */ 131 | @Override 132 | public String toString() { 133 | return "IntegerCompositionIterator=[#" + _currentIndex + ", " 134 | + _currentComposition + "]"; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/combination/simple/SimpleCombinationIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.combination.simple; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.ICombinatoricsVector; 11 | 12 | /** 13 | * Iterator for the simple combination generator 14 | * 15 | * @param Type of the elements in the combinations 16 | * @author Dmytro Paukov 17 | * @version 2.0 18 | * @see ICombinatoricsVector 19 | * @see SimpleCombinationGenerator 20 | */ 21 | class SimpleCombinationIterator implements 22 | Iterator> { 23 | 24 | /** 25 | * Generator 26 | */ 27 | final SimpleCombinationGenerator _generator; 28 | 29 | /** 30 | * Size of the original vector/set 31 | */ 32 | final int _lengthN; 33 | 34 | /** 35 | * Size of the generated combination. 36 | */ 37 | final int _lengthK; 38 | 39 | /** 40 | * Current simple combination 41 | */ 42 | ICombinatoricsVector _currentSimpleCombination = null; 43 | 44 | /** 45 | * Index of the current combination 46 | */ 47 | long _currentIndex = 0; 48 | 49 | /** 50 | * Helper array 51 | */ 52 | private int[] _bitVector = null; 53 | 54 | /** 55 | * Criteria to stop iteration 56 | */ 57 | private int _endIndex = 0; 58 | 59 | /** 60 | * Constructor 61 | * 62 | * @param generator Generator of the simple combinations 63 | */ 64 | SimpleCombinationIterator(SimpleCombinationGenerator generator) { 65 | _generator = generator; 66 | _lengthN = generator.getOriginalVector().getSize(); 67 | _lengthK = generator.getCombinationLength(); 68 | _currentSimpleCombination = createVector(); 69 | _bitVector = new int[_lengthK + 1]; 70 | init(); 71 | } 72 | 73 | /** 74 | * Initialization 75 | */ 76 | private void init() { 77 | 78 | for (int i = 0; i <= _lengthK; i++) { 79 | _bitVector[i] = i; 80 | } 81 | if (_lengthN > 0) { 82 | _endIndex = 1; 83 | } 84 | _currentIndex = 0; 85 | } 86 | 87 | /** 88 | * Returns true if all combinations were iterated, otherwise false 89 | */ 90 | @Override 91 | public boolean hasNext() { 92 | return !((_endIndex == 0) || (_lengthK > _lengthN)); 93 | } 94 | 95 | /** 96 | * Moves to the next combination 97 | */ 98 | @Override 99 | public ICombinatoricsVector next() { 100 | _currentIndex++; 101 | 102 | for (int i = 1; i <= _lengthK; i++) { 103 | int index = _bitVector[i] - 1; 104 | if (_generator.getOriginalVector().getSize() > 0) { 105 | _currentSimpleCombination.setValue(i - 1, _generator 106 | .getOriginalVector().getValue(index)); 107 | } 108 | } 109 | 110 | _endIndex = _lengthK; 111 | 112 | while (_bitVector[_endIndex] == _lengthN - _lengthK + _endIndex) { 113 | _endIndex--; 114 | if (_endIndex == 0) { 115 | break; 116 | } 117 | } 118 | _bitVector[_endIndex]++; 119 | for (int i = _endIndex + 1; i <= _lengthK; i++) { 120 | _bitVector[i] = _bitVector[i - 1] + 1; 121 | } 122 | 123 | // return the current combination 124 | return createVector(_currentSimpleCombination); 125 | } 126 | 127 | @Override 128 | public void remove() { 129 | throw new UnsupportedOperationException(); 130 | } 131 | 132 | /** 133 | * Returns the current combination as a string 134 | * 135 | * @see java.lang.Object#toString() 136 | */ 137 | @Override 138 | public String toString() { 139 | return "SimpleCombinationIterator=[#" + _currentIndex + ", " + _currentSimpleCombination + "]"; 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/composition/CompositionIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.composition; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createSubSetGenerator; 8 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 9 | 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import org.paukov.combinatorics.Generator; 13 | import org.paukov.combinatorics.ICombinatoricsVector; 14 | 15 | /** 16 | * Iterator for enumeration of all compositions 17 | * 18 | * @author Dmytro Paukov 19 | * @version 2.0 20 | * @see ICombinatoricsVector 21 | * @see CompositionGenerator 22 | */ 23 | class CompositionIterator implements 24 | Iterator> { 25 | 26 | final CompositionGenerator _generator; 27 | /** 28 | * Subset generator 29 | */ 30 | final Generator _subsetGenerator; 31 | /** 32 | * Subset iterator 33 | */ 34 | final Iterator> _subsetIterator; 35 | /** 36 | * Current composition 37 | */ 38 | ICombinatoricsVector _currentComposition = null; 39 | /** 40 | * Current index of the weak composition 41 | */ 42 | long _currentIndex = 0; 43 | /** 44 | * Current subset 45 | */ 46 | ICombinatoricsVector _currentSubset = null; 47 | 48 | /** 49 | * Constructor of the iterator 50 | * 51 | * @param generator The Composition generator 52 | */ 53 | CompositionIterator(CompositionGenerator generator) { 54 | super(); 55 | _generator = generator; 56 | 57 | ICombinatoricsVector coreSet = createVector(); 58 | 59 | for (int i = 1; i < this._generator._initialValue; i++) { 60 | coreSet.addValue(i); 61 | } 62 | 63 | _subsetGenerator = createSubSetGenerator(coreSet); 64 | 65 | _subsetIterator = _subsetGenerator.iterator(); 66 | } 67 | 68 | /** 69 | * Returns the next composition 70 | */ 71 | @Override 72 | public ICombinatoricsVector next() { 73 | _currentIndex++; 74 | _currentSubset = this._subsetIterator.next(); 75 | return getCurrentItem(); 76 | } 77 | 78 | /** 79 | * Returns true when all composition are iterated 80 | */ 81 | @Override 82 | public boolean hasNext() { 83 | return this._subsetIterator.hasNext(); 84 | } 85 | 86 | /** 87 | * Returns current composition 88 | */ 89 | private ICombinatoricsVector getCurrentItem() { 90 | 91 | _currentComposition = createVector(); 92 | 93 | List vector = _currentSubset.getVector(); 94 | java.util.Iterator itr = vector.iterator(); 95 | 96 | int currentValueSubSet = 0; 97 | int indexCompositionElement = 0; 98 | int valueCompositionElement = 0; 99 | 100 | while (itr.hasNext()) { 101 | Integer currentSubsetElement = itr.next(); 102 | valueCompositionElement = currentSubsetElement - currentValueSubSet; 103 | _currentComposition.setValue(indexCompositionElement, 104 | valueCompositionElement); 105 | indexCompositionElement++; 106 | currentValueSubSet = currentSubsetElement; 107 | } 108 | _currentComposition.setValue(indexCompositionElement, 109 | _generator._initialValue - currentValueSubSet); 110 | 111 | return _currentComposition; 112 | } 113 | 114 | @Override 115 | public void remove() { 116 | throw new UnsupportedOperationException(); 117 | } 118 | 119 | /** 120 | * Returns composition as a string 121 | * 122 | * @see java.lang.Object#toString() 123 | */ 124 | @Override 125 | public String toString() { 126 | return "CompositionIterator=[#" + _currentIndex + ", " 127 | + _currentComposition + "]"; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/permutations/PermutationWithRepetitionIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.permutations; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import org.paukov.combinatorics.ICombinatoricsVector; 13 | 14 | /** 15 | * Iterator for the permutation with repetitions 16 | * 17 | * @param Type of the elements in the permutations 18 | * @author Dmytro Paukov 19 | * @version 2.0 20 | * @see ICombinatoricsVector 21 | * @see PermutationWithRepetitionGenerator 22 | */ 23 | class PermutationWithRepetitionIterator implements 24 | Iterator> { 25 | 26 | /** 27 | * Generator 28 | */ 29 | final PermutationWithRepetitionGenerator _generator; 30 | 31 | /** 32 | * Number of elements in the core vector 33 | */ 34 | final int _n; 35 | 36 | /** 37 | * Number of elements in the generated permutations 38 | */ 39 | final int _k; 40 | 41 | /** 42 | * Current permutation 43 | */ 44 | ICombinatoricsVector _currentPermutation = null; 45 | 46 | /** 47 | * Index of the current permutation 48 | */ 49 | long _currentIndex = 0; 50 | 51 | /** 52 | * Internal data 53 | */ 54 | private int[] _bitVector = null; 55 | 56 | /** 57 | * Constructor 58 | * 59 | * @param generator Generator 60 | */ 61 | PermutationWithRepetitionIterator( 62 | PermutationWithRepetitionGenerator generator) { 63 | _generator = generator; 64 | _n = generator.getOriginalVector().getSize(); 65 | _k = generator.getPermutationLength(); 66 | 67 | List list = new ArrayList(_k); 68 | T defaultValue = generator.getOriginalVector().getValue(0); 69 | for (int i = 0; i < _k; i++) { 70 | list.add(defaultValue); 71 | } 72 | 73 | _currentPermutation = createVector(list); 74 | 75 | _bitVector = new int[_k + 2]; 76 | init(); 77 | } 78 | 79 | /** 80 | * Initializes iteration process 81 | * 82 | * @see org.paukov.combinatorics.Iterator#first() 83 | */ 84 | private void init() { 85 | for (int j = 0; j <= _k; j++) { 86 | _bitVector[j] = 0; 87 | } 88 | _currentIndex = 0; 89 | } 90 | 91 | /** 92 | * Returns true if all permutations have been iterated 93 | * 94 | * @see Iterator#hasNext() 95 | */ 96 | @Override 97 | public boolean hasNext() { 98 | return (_bitVector[_k] != 1); 99 | } 100 | 101 | /** 102 | * Moves to the next permutation 103 | * 104 | * @see Iterator#next() 105 | */ 106 | @Override 107 | public ICombinatoricsVector next() { 108 | _currentIndex++; 109 | 110 | for (int j = _k - 1; j >= 0; j--) { 111 | int index = _bitVector[j]; 112 | _currentPermutation.setValue(j, _generator.getOriginalVector() 113 | .getValue(index)); 114 | } 115 | 116 | int i = 0; 117 | while (_bitVector[i] == _n - 1) { 118 | if (i < _k + 1) { 119 | _bitVector[i] = 0; 120 | } else { 121 | _bitVector[_k] = 1; 122 | return createVector(_currentPermutation); 123 | } 124 | i++; 125 | } 126 | 127 | _bitVector[i]++; 128 | return createVector(_currentPermutation); 129 | 130 | } 131 | 132 | @Override 133 | public void remove() { 134 | throw new UnsupportedOperationException(); 135 | } 136 | 137 | /** 138 | * Returns the current permutation as a string 139 | * 140 | * @see java.lang.Object#toString() 141 | */ 142 | @Override 143 | public String toString() { 144 | return "PermutationWithRepetitionIterator=[#" + _currentIndex + ", " + _currentPermutation 145 | + "]"; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/combination/multi/MultiCombinationGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.combination.multi; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | import org.paukov.combinatorics.util.Util; 13 | 14 | /** 15 | * This generator generates multi-combinations (with repetitions) from specified 16 | * core set by specified length. Core set and length are specified in the 17 | * constructor of generator 18 | *

19 | * A k-multicombination or k-combination with repetition of a finite set S is 20 | * given by a sequence of k not necessarily distinct elements of S, where order 21 | * is not taken into account. 22 | *

23 | * As an example. Suppose there are 2 types of fruits (apple and orange) at a 24 | * grocery store, and you want to buy 3 pieces of fruit. You could select 25 | *

    26 | *
  • (apple, apple, apple) 27 | *
  • (apple, apple, orange) 28 | *
  • (apple, orange, orange) 29 | *
  • (orange, orange, orange) 30 | *
31 | *

32 | * Generate 3-combinations with repetitions of the set (apple, orange). 33 | *

34 | *

35 | *

36 | * 37 | *
 38 |  *
 39 |  * // Create the initial vector of (apple, orange)
 40 |  * ICombinatoricsVector<String> initialVector = CombinatoricsFactory.createVector(new String[] {
 41 |  * 		"apple", "orange" });
 42 |  *
 43 |  * // Create a multi-combination generator to generate 3-combinations of
 44 |  * // the initial vector
 45 |  * Generator<String> gen = CombinatoricsFactory.createMultiCombinationGenerator(initialVector, 3);
 46 |  *
 47 |  * // Print all possible combinations
 48 |  * for (ICombinatoricsVector<String> combination : gen) {
 49 |  * 	System.out.println(combination);
 50 |  * }
 51 |  * 
52 | * 53 | *
54 | *

55 | * 56 | * @param Type of elements in the combination 57 | * @author Dmytro Paukov 58 | * @version 2.0 59 | * @see MultiCombinationIterator 60 | */ 61 | public class MultiCombinationGenerator extends Generator { 62 | 63 | protected final ICombinatoricsVector _originalVector; 64 | protected final int _combinationLength; 65 | 66 | /** 67 | * Constructor 68 | * 69 | * @param originalVector Original/initial vector which is used for combination generation 70 | * @param combinationsLength Length of combination to generate 71 | */ 72 | public MultiCombinationGenerator(ICombinatoricsVector originalVector, 73 | int combinationsLength) { 74 | _originalVector = createVector(originalVector); 75 | if (combinationsLength < 0) { 76 | _combinationLength = 0; 77 | } else { 78 | _combinationLength = combinationsLength; 79 | } 80 | } 81 | 82 | /** 83 | * Returns core set 84 | * 85 | * @return Returns the _originalVector. 86 | */ 87 | public ICombinatoricsVector getOriginalVector() { 88 | return _originalVector; 89 | } 90 | 91 | /** 92 | * Returns length of combinations 93 | * 94 | * @return Returns the _combinationLength. 95 | */ 96 | public int getCombinationLength() { 97 | return _combinationLength; 98 | } 99 | 100 | /** 101 | * Returns number of generated combinations with repetitions 102 | */ 103 | public long getNumberOfGeneratedObjects() { 104 | return Util.combination(_originalVector.getSize() + _combinationLength 105 | - 1, _combinationLength); 106 | } 107 | 108 | /** 109 | * Creates iterator of combinations with repetitions 110 | */ 111 | @Override 112 | public Iterator> iterator() { 113 | return new MultiCombinationIterator<>(this); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/composition/CompositionGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.composition; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | import org.paukov.combinatorics.util.Util; 13 | 14 | /** 15 | * A composition of an integer n is a way of writing n as the sum of a sequence of (strictly) 16 | * positive integers. This class generates the composition if a positive integer value. 17 | * 18 | * A composition of an integer n is a way of writing n as the sum of a sequence of (strictly) 19 | * positive integers. Two sequences that differ in the order of their terms define different 20 | * compositions of their sum, while they are considered to define the same partition of that 21 | * number. 22 | * 23 | * The sixteen compositions of 5 are: 24 | *

 25 |  *   5
 26 |  *   4+1
 27 |  *   3+2
 28 |  *   3+1+1
 29 |  *   2+3
 30 |  *   2+2+1
 31 |  *   2+1+2
 32 |  *   2+1+1+1
 33 |  *   1+4
 34 |  *   1+3+1
 35 |  *   1+2+2
 36 |  *   1+2+1+1
 37 |  *   1+1+3
 38 |  *   1+1+2+1
 39 |  *   1+1+1+2
 40 |  *   1+1+1+1+1.
 41 |  * 
42 | * 43 | * Compare this with the seven partitions of 5: 5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1. 44 | * 45 | * 46 | * Example. Generate compositions all possible integer compositions of 5. 47 | * 48 | *
 49 |  *   // Create an instance of the integer composition generator to generate all possible
 50 |  * compositions of 5
 51 |  *   Generator<Integer> gen = CombinatoricsFactory.createCompositionGenerator(5);
 52 |  *
 53 |  *   // Print the compositions
 54 |  *   for (ICombinatoricsVector<Integer> p : gen) {
 55 |  *      System.out.println(p);
 56 |  *   }
 57 |  * 
58 | * 59 | * And the result 60 | * 61 | *
 62 |  *    CombinatoricsVector=([5], size=1)
 63 |  *    CombinatoricsVector=([1, 4], size=2)
 64 |  *    CombinatoricsVector=([2, 3], size=2)
 65 |  *    CombinatoricsVector=([1, 1, 3], size=3)
 66 |  *    CombinatoricsVector=([3, 2], size=2)
 67 |  *    CombinatoricsVector=([1, 2, 2], size=3)
 68 |  *    CombinatoricsVector=([2, 1, 2], size=3)
 69 |  *    CombinatoricsVector=([1, 1, 1, 2], size=4)
 70 |  *    CombinatoricsVector=([4, 1], size=2)
 71 |  *    CombinatoricsVector=([1, 3, 1], size=3)
 72 |  *    CombinatoricsVector=([2, 2, 1], size=3)
 73 |  *    CombinatoricsVector=([1, 1, 2, 1], size=4)
 74 |  *    CombinatoricsVector=([3, 1, 1], size=3)
 75 |  *    CombinatoricsVector=([1, 2, 1, 1], size=4)
 76 |  *    CombinatoricsVector=([2, 1, 1, 1], size=4)
 77 |  *    CombinatoricsVector=([1, 1, 1, 1, 1], size=5)
 78 |  * 
79 | * 80 | * @author Dmytro Paukov 81 | * @version 2.0 82 | * @see CompositionIterator 83 | */ 84 | public class CompositionGenerator extends Generator { 85 | 86 | public static final int MAXN = 100; 87 | 88 | protected final Integer _initialValue; 89 | 90 | /** 91 | * Constructor 92 | * 93 | * @param n A positive integer value 94 | */ 95 | public CompositionGenerator(Integer n) { 96 | super(); 97 | this._initialValue = n; 98 | } 99 | 100 | /** 101 | * Returns the value which is used for generating the compositions. This value is 102 | * returned as an element of the single value vector. 103 | */ 104 | @Override 105 | public ICombinatoricsVector getOriginalVector() { 106 | return createVector(_initialValue); 107 | } 108 | 109 | /** 110 | * Returns number of the compositions 111 | */ 112 | @Override 113 | public long getNumberOfGeneratedObjects() { 114 | return Util.pow2(_initialValue - 1); 115 | } 116 | 117 | /** 118 | * Creates the iterator over all compositions 119 | */ 120 | @Override 121 | public Iterator> iterator() { 122 | return new CompositionIterator(this); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/IntegerFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import org.paukov.combinatorics.composition.IntegerCompositionGenerator; 8 | import org.paukov.combinatorics.subsets.IntegerSubSetGenerator; 9 | 10 | /** 11 | * This is a special factory to create integer vectors and generators. 12 | * 13 | * @author Dmytro Paukov 14 | * @version 2.0 15 | * @see IntegerVector 16 | * @see IntegerGenerator 17 | */ 18 | public class IntegerFactory { 19 | 20 | /** 21 | * Creates an empty integer vector instance 22 | * 23 | * @return The empty vector 24 | */ 25 | public static IntegerVector createIntegerVector() { 26 | return new IntegerVector(0); 27 | } 28 | 29 | /** 30 | * Creates an empty integer vector instance 31 | * 32 | * @return The empty vector 33 | */ 34 | public static IntegerVector createIntegerVector(int size) { 35 | return new IntegerVector(size); 36 | } 37 | 38 | /** 39 | * Creates an integer vector from the given integer array 40 | * 41 | * @param array The array 42 | * @return The integer vector 43 | */ 44 | public static IntegerVector createIntegerVector(int[] array) { 45 | return new IntegerVector(array); 46 | } 47 | 48 | /** 49 | * Creates an integer vector from the given integer array by the length 50 | * len 51 | * 52 | * @param array The array 53 | * @param len the length 54 | * @return The integer vector 55 | */ 56 | public static IntegerVector createIntegerVector(int[] array, int len) { 57 | return new IntegerVector(array, len); 58 | } 59 | 60 | /** 61 | * Creates a sub-set generator 62 | * 63 | * @param originalVector The initial vector 64 | */ 65 | public static IntegerGenerator createIntegerSubSetGenerator( 66 | IntegerVector originalVector) { 67 | return new IntegerSubSetGenerator(originalVector); 68 | } 69 | 70 | /** 71 | * Creates a sub-set generator 72 | * 73 | * @param originalVector The initial vector 74 | * @param treatAsIdentical true if the sub sets have to be treated as identical 75 | * @return An instance of the generator 76 | * @see IntegerSubSetGenerator 77 | */ 78 | public static IntegerGenerator createIntegerSubSetGenerator( 79 | IntegerVector originalVector, boolean treatAsIdentical) { 80 | return new IntegerSubSetGenerator(originalVector, treatAsIdentical); 81 | } 82 | 83 | /** 84 | * Creates a composition generator 85 | * 86 | * @param n The initial value 87 | */ 88 | public static IntegerGenerator createIntegerCompositionGenerator(Integer n) { 89 | return new IntegerCompositionGenerator(n); 90 | } 91 | 92 | /** 93 | * This method creates a combinatorics vector of (1, 2,.., n) 94 | * 95 | * @param n The value of the number of the elements 96 | * @return The vector 97 | */ 98 | public static IntegerVector range(int n) { 99 | if (n < 0) { 100 | throw new IllegalArgumentException( 101 | "Range value must be more or equal to 0"); 102 | } 103 | 104 | // If range is zero return an empty vector 105 | if (n == 0) { 106 | return new IntegerVector(); 107 | } 108 | 109 | int[] array = new int[n]; 110 | for (int i = 0; i < n; i++) { 111 | array[i] = i + 1; 112 | } 113 | 114 | return new IntegerVector(array); 115 | } 116 | 117 | /** 118 | * This method creates a combinatorics vector of (from, from + 1,.., to-1, 119 | * to) 120 | * 121 | * @param from The first value 122 | * @param to The second value 123 | * @return The vector 124 | */ 125 | public static IntegerVector range(int from, int to) { 126 | if (from > to) { 127 | throw new IllegalArgumentException( 128 | "From parameter must be less then To parameter"); 129 | } 130 | 131 | int[] array = new int[to - from + 1]; 132 | for (int i = 0; i < to - from + 1; i++) { 133 | array[i] = i + from; 134 | } 135 | 136 | return new IntegerVector(array); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/permutations/PermutationWithRepetitionGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.permutations; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.CombinatoricsFactory; 11 | import org.paukov.combinatorics.Generator; 12 | import org.paukov.combinatorics.ICombinatoricsVector; 13 | 14 | /** 15 | * This generator generates permutations with repetitions from the specified vector by specified 16 | * length 17 | * 18 | * The permutation may have more elements than slots. For example, the three possible 19 | * permutation of 12 in three slots are: 111, 211, 121, 221, 112, 212, 122, and 222. 20 | * 21 | * Let's generate all possible permutations with repetitions of 3 elements from the set of apple and 22 | * orange: 23 | * 24 | *
 25 |  *
 26 |  * // Create the initial vector of 2 elements (apple, orange)
 27 |  * ICombinatoricsVector<String> originalVector = CombinatoricsFactory.createVector(new String[] {
 28 |  * "apple", "orange" });
 29 |  *
 30 |  * // Create the generator by calling the appropriate method in the Factory class.
 31 |  * // Set the second parameter as 3, since we will generate 3-elemets permutations
 32 |  * Generator<String> gen = CombinatoricsFactory.createPermutationWithRepetitionGenerator(originalVector,
 33 |  * 3);
 34 |  *
 35 |  * // Print the result
 36 |  * for (ICombinatoricsVector<String> perm : gen)
 37 |  *    System.out.println( perm );
 38 |  * 
39 | * 40 | * And the result 41 | * 42 | *
 43 |  *   CombinatoricsVector=([apple, apple, apple], size=3)
 44 |  *   CombinatoricsVector=([orange, apple, apple], size=3)
 45 |  *   CombinatoricsVector=([apple, orange, apple], size=3)
 46 |  *   CombinatoricsVector=([orange, orange, apple], size=3)
 47 |  *   CombinatoricsVector=([apple, apple, orange], size=3)
 48 |  *   CombinatoricsVector=([orange, apple, orange], size=3)
 49 |  *   CombinatoricsVector=([apple, orange, orange], size=3)
 50 |  *   CombinatoricsVector=([orange, orange, orange], size=3)
 51 |  * 
52 | * 53 | * @param Type of the elements in the permutations 54 | * @author Dmytro Paukov 55 | * @version 2.0 56 | * @see ICombinatoricsVector 57 | * @see PermutationWithRepetitionIterator 58 | * @see CombinatoricsFactory 59 | */ 60 | public class PermutationWithRepetitionGenerator extends Generator { 61 | 62 | /** 63 | * Original vector which is used as the base for the permutations 64 | */ 65 | protected final ICombinatoricsVector _originalVector; 66 | 67 | /** 68 | * Number of elements in the generated permutation 69 | */ 70 | protected final int _permutationLength; 71 | 72 | /** 73 | * Constructor 74 | * 75 | * @param originalVector core vector which is used as the base for generator 76 | * @param permutationLength Number of elements in the generated permutation 77 | */ 78 | public PermutationWithRepetitionGenerator( 79 | ICombinatoricsVector originalVector, int permutationLength) { 80 | _originalVector = createVector(originalVector); 81 | _permutationLength = permutationLength; 82 | } 83 | 84 | /** 85 | * Creates an iterator 86 | * 87 | * @see org.paukov.combinatorics.Generator#iterator() 88 | */ 89 | @Override 90 | public Iterator> iterator() { 91 | return new PermutationWithRepetitionIterator(this); 92 | } 93 | 94 | /** 95 | * Returns core vector 96 | */ 97 | @Override 98 | public ICombinatoricsVector getOriginalVector() { 99 | return _originalVector; 100 | } 101 | 102 | /** 103 | * Returns number of generated permutations 104 | */ 105 | @Override 106 | public long getNumberOfGeneratedObjects() { 107 | return (long) Math.pow(_originalVector.getSize(), _permutationLength); 108 | } 109 | 110 | /** 111 | * Returns the number of elements in the generated permutations 112 | */ 113 | public int getPermutationLength() { 114 | return _permutationLength; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/combination/multi/MultiCombinationIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.combination.multi; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.ICombinatoricsVector; 11 | 12 | /** 13 | * Multi-combinations iterator for enumerating combinations with repetitions 14 | * 15 | * @param Type of the elements in the combinations 16 | * @author Dmytro Paukov 17 | * @version 2.0 18 | * @see ICombinatoricsVector 19 | * @see MultiCombinationGenerator 20 | */ 21 | class MultiCombinationIterator implements 22 | Iterator> { 23 | 24 | /** 25 | * Generator 26 | */ 27 | final MultiCombinationGenerator _generator; 28 | 29 | /** 30 | * Size of the original vector/set 31 | */ 32 | final int _lengthN; 33 | 34 | /** 35 | * Size of the combinations (number of elements) to generate 36 | */ 37 | final int _lengthK; 38 | 39 | /** 40 | * Current combination 41 | */ 42 | ICombinatoricsVector _currentCombination = null; 43 | 44 | /** 45 | * Index of the current combination 46 | */ 47 | long _currentIndex = 0; 48 | 49 | /** 50 | * A helper array 51 | */ 52 | private int[] _bitVector = null; 53 | 54 | /** 55 | * Criteria to stop iteration 56 | */ 57 | private boolean _end = false; 58 | 59 | /** 60 | * Constructor 61 | * 62 | * @param generator Multi-combinations generator 63 | */ 64 | MultiCombinationIterator(MultiCombinationGenerator generator) { 65 | _generator = generator; 66 | _lengthN = generator.getOriginalVector().getSize(); 67 | _currentCombination = createVector(); 68 | _bitVector = new int[generator.getCombinationLength()]; 69 | _lengthK = generator.getCombinationLength() - 1; 70 | init(); 71 | } 72 | 73 | /** 74 | * Initialization of the iterator 75 | */ 76 | private void init() { 77 | 78 | for (int i = 0; i < _generator.getCombinationLength(); i++) { 79 | _bitVector[i] = 0; 80 | } 81 | _end = false; 82 | _currentIndex = 0; 83 | 84 | } 85 | 86 | /** 87 | * Returns true if all combinations were iterated, otherwise false 88 | */ 89 | @Override 90 | public boolean hasNext() { 91 | return (_end != true); 92 | } 93 | 94 | /** 95 | * Moves to the next combination 96 | */ 97 | @Override 98 | public ICombinatoricsVector next() { 99 | _currentIndex++; 100 | 101 | for (int i = 0; i < _generator.getCombinationLength(); i++) { 102 | int index = _bitVector[i]; 103 | if (_generator.getOriginalVector().getSize() > 0) { 104 | _currentCombination.setValue(i, _generator.getOriginalVector() 105 | .getValue(index)); 106 | } 107 | } 108 | 109 | if (_bitVector.length > 0) { 110 | _bitVector[_lengthK]++; 111 | 112 | if (_bitVector[_lengthK] > _lengthN - 1) { 113 | int index = -1; 114 | for (int i = 1; i <= _bitVector.length; i++) { 115 | if (_lengthK - i >= 0) { 116 | if (_bitVector[_lengthK - i] < _lengthN - 1) { 117 | index = _lengthK - i; 118 | break; 119 | } 120 | } 121 | } 122 | 123 | if (index != -1) { 124 | _bitVector[index]++; 125 | 126 | for (int j = 1; j < _bitVector.length - index; j++) { 127 | _bitVector[index + j] = _bitVector[index]; 128 | } 129 | 130 | } else { 131 | _end = true; 132 | } 133 | 134 | } 135 | } else { 136 | _end = true; 137 | } 138 | 139 | // return the current combination 140 | return createVector(_currentCombination); 141 | } 142 | 143 | @Override 144 | public void remove() { 145 | throw new UnsupportedOperationException(); 146 | } 147 | 148 | /** 149 | * Returns the current combination as a string 150 | * 151 | * @see java.lang.Object#toString() 152 | */ 153 | @Override 154 | public String toString() { 155 | return "MultiCombinationIterator=[#" + _currentIndex + ", " + _currentCombination + "]"; 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/partition/PartitionGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.partition; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.Generator; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | 13 | /** 14 | * In number theory, a partition of a positive integer n is a way of writing n 15 | * as a sum of positive integers. Two sums that differ only in the order of 16 | * their summands are considered to be the same partition; if order matters then 17 | * the sum becomes a composition. A summand in a partition is also called a 18 | * part. 19 | *

20 | * WARNING. Be careful because number of all partitions can be very high even 21 | * for not great given N. 22 | *

23 | * The partitions of 5 are listed below: 24 | *

    25 | *
  1. 1 + 1 + 1 + 1 + 1 26 | *
  2. 2 + 1 + 1 + 1 27 | *
  3. 2 + 2 + 1 28 | *
  4. 3 + 1 + 1 29 | *
  5. 3 + 2 30 | *
  6. 4 + 1 31 | *
  7. 5 32 | *
33 | *

34 | * The number of partitions of n is given by the partition function p(n). In 35 | * number theory, the partition function p(n) represents the number of possible 36 | * partitions of a natural number n, which is to say the number of distinct (and 37 | * order independent) ways of representing n as a sum of natural numbers. 38 | *

39 | * Let's generate all possible partitions of 5: 40 | *

41 | *

42 | * 43 | *
 44 |  * // Create an instance of the partition generator to generate all
 45 |  * // possible partitions of 5
 46 |  * Generator<Integer> gen = CombinatoricsFactory.createPartitionGenerator(5);
 47 |  *
 48 |  * // Print the partitions
 49 |  * for (ICombinatoricsVector<Integer> p : gen) {
 50 |  * 	System.out.println(p);
 51 |  * }
 52 |  *
 53 |  * 
54 | * 55 | *
56 | *

57 | * And the result of all 7 integer possible partitions 58 | *

59 | *

60 | * 61 | *
 62 |  *   CombinatoricsVector=([1, 1, 1, 1, 1], size=5)
 63 |  *   CombinatoricsVector=([2, 1, 1, 1], size=4)
 64 |  *   CombinatoricsVector=([2, 2, 1], size=3)
 65 |  *   CombinatoricsVector=([3, 1, 1], size=3)
 66 |  *   CombinatoricsVector=([3, 2], size=2)
 67 |  *   CombinatoricsVector=([4, 1], size=2)
 68 |  *   CombinatoricsVector=([5], size=1)
 69 |  * 
70 | * 71 | *
72 | *

73 | * 74 | * @author Dmytro.Paukov 75 | * @version 2.0 76 | * @see ICombinatoricsVector 77 | * @see PartitionIterator 78 | */ 79 | public class PartitionGenerator extends Generator { 80 | 81 | public static final int MAXN = 100; 82 | 83 | protected final Integer _initialValue; 84 | 85 | /** 86 | * Constructor 87 | * 88 | * @param n An integer value to generate partitions 89 | */ 90 | public PartitionGenerator(Integer n) { 91 | _initialValue = n; 92 | } 93 | 94 | /** 95 | * Creates iterator to enumerate all partitions 96 | */ 97 | @Override 98 | public Iterator> iterator() { 99 | return new PartitionIterator(this); 100 | } 101 | 102 | /** 103 | * Returns the value which is used for generating the partitions. This value is 104 | * returned as a vector, that has only one element. 105 | */ 106 | @Override 107 | public ICombinatoricsVector getOriginalVector() { 108 | return createVector(_initialValue); 109 | } 110 | 111 | /** 112 | * Returns approximated number of partitions for given positive value. 113 | *

114 | * Note.Exact value of number of partitions can be obtained from 115 | * actual generated list of partitions. 116 | *

117 | * WARNING! Be careful because number of all partitions can be very 118 | * high even for not great given value of N. 119 | */ 120 | @Override 121 | public long getNumberOfGeneratedObjects() { 122 | 123 | if (_initialValue == 0) { 124 | return 0; 125 | } 126 | 127 | if (_initialValue > 0 && _initialValue <= MAXN) { 128 | double result = 2.0 * _initialValue / 3.0; 129 | result = Math.exp(Math.PI * Math.sqrt(result)); 130 | result /= 4.0 * _initialValue * Math.sqrt(3); 131 | return (long) result; 132 | } 133 | 134 | throw new RuntimeException( 135 | "Unable to calculate the number of the partitions for the value N=" + _initialValue); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/util/UtilTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.util; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | import java.math.BigDecimal; 10 | import org.junit.Test; 11 | 12 | /** 13 | * @author Dmytro Paukov 14 | */ 15 | public class UtilTest { 16 | 17 | private static BigDecimal[][] toBigDecimal(double[][] a) { 18 | int n = a.length; 19 | BigDecimal[][] b = new BigDecimal[n][n]; 20 | for (int i = 0; i < n; i++) { 21 | for (int j = 0; j < n; j++) { 22 | b[i][j] = BigDecimal.valueOf(a[i][j]); 23 | } 24 | } 25 | return b; 26 | } 27 | 28 | @Test 29 | public void determinantCrout1Test() { 30 | 31 | BigDecimal result = Util.detCrout(toBigDecimal(new double[][]{ 32 | {2, 4, 3, 5, 4}, {5, 4, 0, 2, 4}, {0, 5, 5, 2, 3}, 33 | {1, 0, 4, 3, 0}, {0, 5, 1, 4, 4}}), 5); 34 | 35 | assertEquals(279.0, result.doubleValue(), 1e-10); 36 | } 37 | 38 | @Test 39 | public void determinantCrout2Test() { 40 | 41 | BigDecimal result = Util.detCrout(toBigDecimal(new double[][]{ 42 | {3, 2, 2}, {0, 0, 5}, {4, 3, 1}}), 3); 43 | 44 | assertEquals(-5.0, result.doubleValue(), 1e-10); 45 | } 46 | 47 | @Test 48 | public void determinantCrout3Test() { 49 | 50 | BigDecimal result = Util.detCrout(toBigDecimal(new double[][]{ 51 | {2, 2, 2}, {1, 2, 0}, {2, 2, 0}}), 3); 52 | 53 | assertEquals(-4.0, result.doubleValue(), 1e-10); 54 | } 55 | 56 | 57 | @Test 58 | public void test_pow2() { 59 | assertEquals(1L, Util.pow2(-1)); 60 | assertEquals(1L, Util.pow2(0)); 61 | assertEquals(2L, Util.pow2(1)); 62 | assertEquals(4L, Util.pow2(2)); 63 | assertEquals(8L, Util.pow2(3)); 64 | assertEquals(16L, Util.pow2(4)); 65 | assertEquals(32L, Util.pow2(5)); 66 | assertEquals(64L, Util.pow2(6)); 67 | 68 | } 69 | 70 | @Test 71 | public void test_factorial() { 72 | assertEquals(1L, Util.factorial(-1)); 73 | assertEquals(1L, Util.factorial(0)); 74 | assertEquals(1L, Util.factorial(1)); 75 | assertEquals(2L, Util.factorial(2)); 76 | assertEquals(6L, Util.factorial(3)); 77 | assertEquals(24L, Util.factorial(4)); 78 | assertEquals(3628800L, Util.factorial(10)); 79 | assertEquals(2432902008176640000L, Util.factorial(20)); 80 | } 81 | 82 | @Test 83 | public void test_combination() { 84 | assertEquals(1L, Util.combination(21, 0)); 85 | assertEquals(21L, Util.combination(21, 1)); 86 | assertEquals(210L, Util.combination(21, 2)); 87 | assertEquals(1L, Util.combination(21, 21)); 88 | } 89 | 90 | @Test 91 | public void test_big_factorial() { 92 | assertEquals(BigDecimal.ONE, Util.bigFactorial(-1)); 93 | assertEquals(BigDecimal.ONE, Util.bigFactorial(0)); 94 | assertEquals(BigDecimal.ONE, Util.bigFactorial(1)); 95 | assertEquals(BigDecimal.valueOf(2), Util.bigFactorial(2)); 96 | assertEquals(BigDecimal.valueOf(6), Util.bigFactorial(3)); 97 | assertEquals(BigDecimal.valueOf(24), Util.bigFactorial(4)); 98 | assertEquals(BigDecimal.valueOf(3628800), Util.bigFactorial(10)); 99 | assertEquals(new BigDecimal("1307674368000"), Util.bigFactorial(15)); 100 | assertEquals(new BigDecimal("2432902008176640000"), Util.bigFactorial(20)); 101 | assertEquals(new BigDecimal("51090942171709440000"), Util.bigFactorial(21)); 102 | } 103 | 104 | @Test 105 | public void test_minimum() { 106 | assertEquals(1, Util.minimum(1, 2, 3)); 107 | assertEquals(1, Util.minimum(2, 1, 3)); 108 | assertEquals(1, Util.minimum(2, 3, 1)); 109 | } 110 | 111 | @Test 112 | public void test_gcd() { 113 | assertEquals(6, Util.gcd(12, 18)); 114 | assertEquals(1, Util.gcd(103, 45)); 115 | assertEquals(2, Util.gcd(64, 34)); 116 | 117 | assertEquals(45, Util.gcd(0, 45)); 118 | assertEquals(64, Util.gcd(64, 0)); 119 | } 120 | 121 | @Test 122 | public void test_lcm() { 123 | assertEquals(36, Util.lcm(12, 18)); 124 | assertEquals(2070, Util.lcm(46, 45)); 125 | assertEquals(330, Util.lcm(66, 15)); 126 | } 127 | 128 | @Test 129 | public void test_levenshteinDistance() { 130 | assertEquals(1, Util.levenshteinDistance("hello", "helo")); 131 | assertEquals(2, Util.levenshteinDistance("america", "amerigo")); 132 | assertEquals(4, Util.levenshteinDistance("abba", "abcadaba")); 133 | 134 | assertEquals(5, Util.levenshteinDistance("hello", "")); 135 | assertEquals(5, Util.levenshteinDistance("", "hello")); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/partition/PartitionIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.partition; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Iterator; 9 | import java.util.List; 10 | import org.paukov.combinatorics.CombinatoricsFactory; 11 | import org.paukov.combinatorics.ICombinatoricsVector; 12 | 13 | /** 14 | * Iterator for enumerating the all possible integer partitions 15 | * 16 | * @author Dmytro Paukov 17 | * @version 2.0 18 | * @see ICombinatoricsVector 19 | * @see PartitionGenerator 20 | */ 21 | class PartitionIterator implements 22 | Iterator> { 23 | 24 | /** 25 | * Generator 26 | */ 27 | final PartitionGenerator _generator; 28 | 29 | /** 30 | * Current partition 31 | */ 32 | ICombinatoricsVector _currentPartition = null; 33 | 34 | /** 35 | * Index of the current partition 36 | */ 37 | long _currentIndex = 0; 38 | 39 | /** 40 | * Helper vectors 41 | */ 42 | private int[] _mVector = null; 43 | private int[] _zVector = null; 44 | 45 | /** 46 | * Stop criteria 47 | */ 48 | private int _kIndex = 1; 49 | 50 | /** 51 | * Constructor 52 | * 53 | * @param generator Generator 54 | */ 55 | PartitionIterator(PartitionGenerator generator) { 56 | _generator = generator; 57 | _mVector = new int[generator._initialValue + 2]; 58 | _zVector = new int[generator._initialValue + 2]; 59 | init(); 60 | } 61 | 62 | /** 63 | * Initializes the iterator 64 | */ 65 | private void init() { 66 | 67 | if (_generator._initialValue < 1) { 68 | _kIndex = 0; 69 | return; 70 | } 71 | 72 | _currentIndex = 0; 73 | _kIndex = 1; 74 | 75 | setInternalVectorValue(-1, _zVector, 0); 76 | setInternalVectorValue(-1, _mVector, 0); 77 | 78 | setInternalVectorValue(0, _zVector, _generator._initialValue + 1); 79 | setInternalVectorValue(0, _mVector, 0); 80 | 81 | setInternalVectorValue(1, _zVector, 1); 82 | setInternalVectorValue(1, _mVector, _generator._initialValue); 83 | } 84 | 85 | /** 86 | * Returns true if all partitions were enumerated 87 | */ 88 | @Override 89 | public boolean hasNext() { 90 | return _kIndex != 0; 91 | } 92 | 93 | /** 94 | * Moves to the next partition 95 | */ 96 | @Override 97 | public ICombinatoricsVector next() { 98 | _currentIndex++; 99 | createCurrentPartition(_kIndex); 100 | int sum = getInternalVectorValue(_kIndex, _mVector) 101 | * getInternalVectorValue(_kIndex, _zVector); 102 | if (getInternalVectorValue(_kIndex, _mVector) == 1) { 103 | _kIndex--; 104 | sum += getInternalVectorValue(_kIndex, _mVector) 105 | * getInternalVectorValue(_kIndex, _zVector); 106 | } 107 | if (getInternalVectorValue(_kIndex - 1, _zVector) == getInternalVectorValue( 108 | _kIndex, _zVector) + 1) { 109 | _kIndex--; 110 | setInternalVectorValue(_kIndex, _mVector, 111 | getInternalVectorValue(_kIndex, _mVector) + 1); 112 | } else { 113 | setInternalVectorValue(_kIndex, _zVector, 114 | getInternalVectorValue(_kIndex, _zVector) + 1); 115 | setInternalVectorValue(_kIndex, _mVector, 1); 116 | } 117 | if (sum > getInternalVectorValue(_kIndex, _zVector)) { 118 | setInternalVectorValue(_kIndex + 1, _zVector, 1); 119 | setInternalVectorValue(_kIndex + 1, _mVector, sum 120 | - getInternalVectorValue(_kIndex, _zVector)); 121 | _kIndex++; 122 | } 123 | 124 | // return the current partition 125 | return _currentPartition; 126 | } 127 | 128 | /** 129 | * Creates current partition based on the internal vectors 130 | */ 131 | private void createCurrentPartition(int k) { 132 | List list = new ArrayList(); 133 | for (int index = 1; index <= k; index++) { 134 | for (int j = 0; j < getInternalVectorValue(index, _mVector); j++) { 135 | list.add(getInternalVectorValue(index, _zVector)); 136 | } 137 | } 138 | _currentPartition = CombinatoricsFactory.createVector(list); 139 | } 140 | 141 | private int getInternalVectorValue(int index, int[] vector) { 142 | return vector[index + 1]; 143 | } 144 | 145 | private void setInternalVectorValue(int index, int[] vector, int value) { 146 | vector[index + 1] = value; 147 | } 148 | 149 | @Override 150 | public void remove() { 151 | throw new UnsupportedOperationException(); 152 | } 153 | 154 | /** 155 | * Returns the current partition as a string 156 | * 157 | * @see java.lang.Object#toString() 158 | */ 159 | @Override 160 | public String toString() { 161 | return "PartitionIterator=[#" + _currentIndex + ", " + _currentPartition + "]"; 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/permutations/PermutationGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.permutations; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.CombinatoricsFactory; 11 | import org.paukov.combinatorics.Generator; 12 | import org.paukov.combinatorics.ICombinatoricsVector; 13 | import org.paukov.combinatorics.util.Util; 14 | 15 | /** 16 | * This generator generates all possible permutations of the specified initial 17 | * vector 18 | *

19 | * A permutation is an ordering of a set in the context of all possible 20 | * orderings. For example, the set containing the first three digits, 123, has 21 | * six permutations: 123, 132, 213, 231, 312, and 321. 22 | *

23 | * This is an example of the permutations of 3 string items (apple, orange, 24 | * cherry): 25 | *

26 | *

27 | * 28 | *
 29 |  *
 30 |  * // Create the initial vector of 3 elements (apple, orange, cherry)
 31 |  * ICombinatoricsVector<String> originalVector = CombinatoricsFactory
 32 |  * 		.createVector(new String[] { "apple", "orange", "cherry" });
 33 |  *
 34 |  * // Create the permutation generator by calling the appropriate method in the
 35 |  * // Factory class
 36 |  * Generator<String> gen = CombinatoricsFactory.createPermutationGenerator(originalVector);
 37 |  *
 38 |  * // Print the result
 39 |  * for (ICombinatoricsVector<String> perm : gen)
 40 |  * 	System.out.println(perm);
 41 |  *
 42 |  * 
43 | * 44 | *
45 | *

46 | * And the result 47 | *

48 | *

49 | * 50 | *
 51 |  *   CombinatoricsVector=([apple, orange, cherry], size=3)
 52 |  *   CombinatoricsVector=([apple, cherry, orange], size=3)
 53 |  *   CombinatoricsVector=([cherry, apple, orange], size=3)
 54 |  *   CombinatoricsVector=([cherry, orange, apple], size=3)
 55 |  *   CombinatoricsVector=([orange, cherry, apple], size=3)
 56 |  *   CombinatoricsVector=([orange, apple, cherry], size=3)
 57 |  * 
58 | * 59 | *
60 | *

61 | * 62 | * @param Type of the elements in the permutations 63 | * @author Dmytro Paukov 64 | * @version 2.0 65 | * @see ICombinatoricsVector 66 | * @see PermutationIterator 67 | * @see CombinatoricsFactory 68 | */ 69 | public class PermutationGenerator extends Generator { 70 | 71 | protected final boolean _hasDuplicates; 72 | protected final boolean _treatAsIdentical; 73 | 74 | /** 75 | * Initial vector 76 | */ 77 | protected final ICombinatoricsVector _originalVector; 78 | 79 | /** 80 | * Constructor 81 | * 82 | * @param originalVector Vector which is used for permutation generation 83 | */ 84 | public PermutationGenerator(ICombinatoricsVector originalVector) { 85 | _hasDuplicates = originalVector.hasDuplicates(); 86 | _treatAsIdentical = false; 87 | _originalVector = createVector(originalVector); 88 | } 89 | 90 | /** 91 | * Constructor 92 | * 93 | * @param originalVector Vector which is used for permutation generation 94 | * @param treatAsIdentical True if the generator should treat the vector as identical 95 | */ 96 | public PermutationGenerator(ICombinatoricsVector originalVector, 97 | boolean treatAsIdentical) { 98 | _hasDuplicates = originalVector.hasDuplicates(); 99 | _treatAsIdentical = treatAsIdentical; 100 | _originalVector = createVector(originalVector); 101 | } 102 | 103 | /** 104 | * Returns core permutation 105 | * 106 | * @see org.paukov.combinatorics.Generator#getOriginalVector() 107 | */ 108 | public ICombinatoricsVector getOriginalVector() { 109 | return _originalVector; 110 | } 111 | 112 | /** 113 | * Returns the number of all generated permutations 114 | * 115 | * @see org.paukov.combinatorics.Generator#getNumberOfGeneratedObjects() 116 | */ 117 | public long getNumberOfGeneratedObjects() { 118 | if (_originalVector.getSize() == 0) { 119 | return 0; 120 | } 121 | 122 | if (isDuplicateIterator()) { 123 | throw new RuntimeException("The initial vector has duplicates: " 124 | + _originalVector); 125 | } 126 | 127 | return Util.factorial(_originalVector.getSize()); 128 | } 129 | 130 | /** 131 | * Creates an iterator 132 | * 133 | * @see org.paukov.combinatorics.Generator#iterator() 134 | */ 135 | @Override 136 | public Iterator> iterator() { 137 | if (isDuplicateIterator()) { 138 | return new DuplicatedPermutationIterator(this); 139 | } else { 140 | return new PermutationIterator(this); 141 | } 142 | 143 | } 144 | 145 | protected boolean isDuplicateIterator() { 146 | return (!_treatAsIdentical && _hasDuplicates); 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/permutations/DuplicatedPermutationIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.permutations; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import java.util.LinkedHashSet; 11 | import java.util.Set; 12 | import org.paukov.combinatorics.Generator; 13 | import org.paukov.combinatorics.ICombinatoricsVector; 14 | 15 | /** 16 | * Iterator for the permutation generator which contains duplicates 17 | * 18 | * @param Type of elements in the permutations 19 | * @author Dmytro Paukov 20 | * @version 2.0 21 | * @see ICombinatoricsVector 22 | * @see PermutationGenerator 23 | */ 24 | class DuplicatedPermutationIterator implements 25 | Iterator> { 26 | 27 | /** 28 | * Generator 29 | */ 30 | final Generator _generator; 31 | 32 | /** 33 | * Number of elements in the permutations 34 | */ 35 | final int _length; 36 | 37 | /** 38 | * Current permutation 39 | */ 40 | ICombinatoricsVector _currentPermutation; 41 | 42 | /** 43 | * Current index of current permutation 44 | */ 45 | long _currentIndex = 0; 46 | 47 | ICombinatoricsVector _initialOrderedPermutation; 48 | 49 | /** 50 | * Internal data 51 | */ 52 | private int _data[] = null; 53 | private boolean _firstIteration = true; 54 | 55 | /** 56 | * Constructor 57 | * 58 | * @param generator Permutation generator 59 | */ 60 | DuplicatedPermutationIterator(Generator generator) { 61 | _generator = generator; 62 | _length = generator.getOriginalVector().getSize(); 63 | _data = new int[_length]; 64 | 65 | ICombinatoricsVector originalVector = generator.getOriginalVector(); 66 | ICombinatoricsVector initialPermutation = createVector(); 67 | 68 | // Create a set of the initial data 69 | Set initialSet = new LinkedHashSet(originalVector.getVector()); 70 | initialSet.addAll(originalVector.getVector()); 71 | 72 | // Create internal data 73 | int dataValue = 0; 74 | int dataIndex = 0; 75 | 76 | _initialOrderedPermutation = createVector(initialSet); 77 | 78 | for (int i = 0; i < _initialOrderedPermutation.getSize(); i++) { 79 | 80 | T value = _initialOrderedPermutation.getValue(i); 81 | dataValue++; 82 | 83 | if (!initialPermutation.contains(value)) { 84 | // Determine how many duplicates of the value in the original 85 | // vector 86 | int count = originalVector.countElements(value); 87 | 88 | for (int countIndex = 0; countIndex < count; countIndex++) { 89 | _data[dataIndex++] = dataValue; 90 | initialPermutation.addValue(value); 91 | } 92 | } 93 | } 94 | 95 | init(); 96 | } 97 | 98 | private static void swap(int[] data, int k, int l) { 99 | int temp = data[k]; 100 | data[k] = data[l]; 101 | data[l] = temp; 102 | } 103 | 104 | private boolean isFinished() { 105 | int k = _data.length - 2; 106 | while (_data[k] >= _data[k + 1]) { 107 | k--; 108 | if (k < 0) { 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | /** 116 | * Initialize the iteration process 117 | */ 118 | private void init() { 119 | _currentIndex = 0; 120 | 121 | _currentPermutation = createVector(); 122 | 123 | for (int i = 0; i < _length; i++) { 124 | int index = _data[i] - 1; 125 | _currentPermutation.addValue(_initialOrderedPermutation 126 | .getValue(index)); 127 | } 128 | } 129 | 130 | /** 131 | * Return true if the iteration process is finished 132 | */ 133 | @Override 134 | public boolean hasNext() { 135 | return !isFinished() || _firstIteration; 136 | } 137 | 138 | /** 139 | * Moves to the next permutation 140 | */ 141 | @Override 142 | public ICombinatoricsVector next() { 143 | 144 | if (_firstIteration) { 145 | _firstIteration = false; 146 | return _currentPermutation; 147 | } 148 | 149 | int k = _data.length - 2; 150 | 151 | while (_data[k] >= _data[k + 1]) { 152 | k--; 153 | } 154 | 155 | int l = _data.length - 1; 156 | while (_data[k] >= _data[l]) { 157 | l--; 158 | } 159 | swap(_data, k, l); 160 | int length = _data.length - (k + 1); 161 | for (int i = 0; i < length / 2; i++) { 162 | swap(_data, k + 1 + i, _data.length - i - 1); 163 | } 164 | 165 | _currentIndex++; 166 | _currentPermutation = createVector(); 167 | 168 | for (int i = 0; i < _length; i++) { 169 | int index = _data[i] - 1; 170 | _currentPermutation.addValue(_initialOrderedPermutation 171 | .getValue(index)); 172 | } 173 | 174 | return _currentPermutation; 175 | } 176 | 177 | @Override 178 | public void remove() { 179 | throw new UnsupportedOperationException(); 180 | } 181 | 182 | /** 183 | * Returns the current permutation as a string 184 | * 185 | * @see java.lang.Object#toString() 186 | */ 187 | @Override 188 | public String toString() { 189 | return "DuplicatedPermutationIterator=[#" + _currentIndex + ", " 190 | + _currentPermutation + "]"; 191 | } 192 | 193 | } -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/IntegerSubSetGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.subsets; 6 | 7 | import java.util.Iterator; 8 | import org.paukov.combinatorics.IntegerFactory; 9 | import org.paukov.combinatorics.IntegerGenerator; 10 | import org.paukov.combinatorics.IntegerVector; 11 | import org.paukov.combinatorics.util.Util; 12 | 13 | /** 14 | * This generator generates all subsets of the specified set/vector of integer 15 | * values. 16 | *

17 | * A set A is a subset of a set B if A is "contained" inside B. A and B may 18 | * coincide. The relationship of one set being a subset of another is called 19 | * inclusion or sometimes containment. 20 | *

21 | * Examples: 22 | *

    23 | *
  • The set (1, 2) is a proper subset of (1, 2, 3). 24 | *
  • Any set is a subset of itself, but not a proper subset. 25 | *
  • The empty set, denoted by (), is also a subset of any given set X. 26 | *
27 | *

28 | * All subsets of (1, 2, 3) are: 29 | *

    30 | *
  1. () 31 | *
  2. (1) 32 | *
  3. (2) 33 | *
  4. (1, 2) 34 | *
  5. (3) 35 | *
  6. (1, 3) 36 | *
  7. (2, 3) 37 | *
  8. (1, 2, 3) 38 | *
39 | *

40 | * And code which generates all subsets of (1, 2, 3) 41 | *

42 | *

43 | * 44 | *
 45 |  * // Create an initial vector/set
 46 |  * IntegerVector initialSet = IntegerFactory.createIntegerVector(new int[] { 1, 2,
 47 |  * 		3 });
 48 |  *
 49 |  * // Create an instance of the integer subset generator
 50 |  * IntegerGenerator gen = IntegerFactory.createIntegerSubSetGenerator(initialSet);
 51 |  *
 52 |  * // Print the subsets
 53 |  * for (IntegerVector subSet : gen) {
 54 |  * 	System.out.println(subSet);
 55 |  * }
 56 |  * 
57 | * 58 | *
59 | *

60 | * And the result of all 8 possible subsets 61 | *

62 | *

63 | * 64 | *
 65 |  *  IntegerVector=([], size=0)
 66 |  *  IntegerVector=([1], size=1)
 67 |  *  IntegerVector=([2], size=1)
 68 |  *  IntegerVector=([1, 2], size=2)
 69 |  *  IntegerVector=([3], size=1)
 70 |  *  IntegerVector=([1, 3], size=2)
 71 |  *  IntegerVector=([2, 3], size=2)
 72 |  *  IntegerVector=([1, 2, 3], size=3)
 73 |  * 
74 | * 75 | *
76 | *

77 | * Version 2.0 of the combinatoricslib supports sets with duplicates. For 78 | * example, if the original vector contains duplicates like (1, 2, 1, 3), then 79 | * the result will contain 14 subsets (instead of 16):

80 | * 81 | *
 82 |  * ()
 83 |  * (1)
 84 |  * (2)
 85 |  * (1, 2)
 86 |  * (1, 1)
 87 |  * (2, 1)
 88 |  * (1, 2, 1)
 89 |  * (3)
 90 |  * (1, 3)
 91 |  * (2, 3)
 92 |  * (1, 2, 3)
 93 |  * (1, 1, 3)
 94 |  * (2, 1, 3)
 95 |  * (1, 2, 1, 3)
 96 |  * 
97 | * 98 | *
99 | *

100 | * If you still would like to treat the set with duplicates as not identical, 101 | * you should create a generator and set the second parameter of the method 102 | * IntegerFactory.createIntegerSubSetGenerator() as 103 | * false. In this case all 16 subsets will be generated. 104 | *

105 | * Note. If the initial vector contains duplicates then the method 106 | * getNumberOfGeneratedObjects won't be able to return the number 107 | * of the sub sets/lists. It will throw a runtime exception 108 | * 109 | * @author DmytroPaukov 110 | * @version 2.0 111 | * @see IntegerVector 112 | * @see IntegerSubSetIterator 113 | */ 114 | public class IntegerSubSetGenerator extends IntegerGenerator { 115 | 116 | protected final boolean _hasDuplicates; 117 | protected final boolean _treatAsIdentical; 118 | 119 | /** 120 | * Core set 121 | */ 122 | protected final IntegerVector _originalVector; 123 | 124 | /** 125 | * Constructor 126 | * 127 | * @param originalVector Original vector/set 128 | */ 129 | public IntegerSubSetGenerator(IntegerVector originalVector) { 130 | _hasDuplicates = originalVector.hasDuplicates(); 131 | _treatAsIdentical = true; 132 | _originalVector = IntegerFactory.createIntegerVector(originalVector 133 | .getVector()); 134 | } 135 | 136 | /** 137 | * Constructor 138 | * 139 | * @param originalVector Original vector/set 140 | */ 141 | public IntegerSubSetGenerator(IntegerVector originalVector, 142 | boolean treatAsIdentical) { 143 | _hasDuplicates = originalVector.hasDuplicates(); 144 | _treatAsIdentical = treatAsIdentical; 145 | _originalVector = IntegerFactory.createIntegerVector(originalVector 146 | .getVector()); 147 | } 148 | 149 | /** 150 | * Returns the core set 151 | */ 152 | public IntegerVector getOriginalVector() { 153 | return _originalVector; 154 | } 155 | 156 | /** 157 | * Returns the number of the subsets. If the original set contains 158 | * duplicates this method will throw a runtime exception. 159 | */ 160 | public long getNumberOfGeneratedObjects() { 161 | 162 | if (isSubList()) { 163 | throw new RuntimeException("The initial vector has duplicates: " 164 | + _originalVector); 165 | } 166 | 167 | return Util.pow2(_originalVector.getSize()); 168 | } 169 | 170 | /** 171 | * Creates the iterator over the all subsets 172 | */ 173 | public Iterator iterator() { 174 | if (isSubList()) { 175 | return new IntegerSubListIterator(this); 176 | } else { 177 | return new IntegerSubSetIterator(this); 178 | } 179 | } 180 | 181 | protected boolean isSubList() { 182 | return (_treatAsIdentical && _hasDuplicates); 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.googlecode.combinatoricslib 6 | combinatoricslib 7 | 2.4-SNAPSHOT 8 | CombinatoricsLib 9 | Very simple java library to generate permutations, combinations and other 10 | combinatorial sequences. 11 | 12 | 13 | 14 | LGPL v3.0 15 | repo 16 | http://www.gnu.org/licenses/lgpl.html 17 | 18 | 19 | 20 | 21 | scm:git:git://github.com/dpaukov/combinatoricslib.git 22 | scm:git:git://github.com/dpaukov/combinatoricslib.git 23 | 24 | https://github.com/dpaukov/combinatoricslib 25 | 26 | 27 | 28 | Travis CI 29 | https://travis-ci.org/dpaukov/combinatoricslib 30 | 31 | 32 | 33 | GitHub Issues 34 | https://github.com/dpaukov/combinatoricslib 35 | 36 | 37 | 38 | 39 | d.paukov 40 | Dmytro Paukov 41 | d.paukov@gmail.com 42 | 43 | 44 | 45 | 46 | UTF-8 47 | 48 | 49 | 50 | 51 | 52 | maven-compiler-plugin 53 | 3.8.1 54 | 55 | 1.7 56 | 1.7 57 | 58 | 59 | 60 | org.apache.maven.plugins 61 | maven-source-plugin 62 | 3.0.1 63 | 64 | 65 | attach-sources 66 | 67 | jar 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-javadoc-plugin 75 | 3.2.0 76 | 77 | 78 | attach-javadocs 79 | 80 | jar 81 | 82 | 83 | 84 | 85 | public 86 | 87 | 88 | 89 | org.codehaus.mojo 90 | cobertura-maven-plugin 91 | 2.7 92 | 93 | xml 94 | 256m 95 | true 96 | 97 | true 98 | 99 | org.paukov.examples.* 100 | 101 | 102 | org/paukov/examples/*.class 103 | 104 | 105 | 106 | 107 | 108 | 109 | org.eluder.coveralls 110 | coveralls-maven-plugin 111 | 4.3.0 112 | 113 | X1yKwWROG5fUTkWa7YlnnFWJJQvb8LaFQ 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | org.apache.maven.plugins 125 | maven-project-info-reports-plugin 126 | 2.7 127 | 128 | false 129 | 130 | 131 | 132 | 133 | 134 | http://code.google.com/p/combinatoricslib/ 135 | 2009 136 | 137 | 138 | 139 | junit 140 | junit 141 | 4.13.1 142 | test 143 | 144 | 145 | 146 | 147 | 148 | release 149 | 150 | 151 | 152 | org.apache.maven.plugins 153 | maven-gpg-plugin 154 | 1.6 155 | 156 | 157 | sign-artifacts 158 | verify 159 | 160 | sign 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/IntegerVectorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.junit.Assert.assertFalse; 9 | import static org.junit.Assert.assertTrue; 10 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 11 | 12 | import org.junit.Test; 13 | 14 | /** 15 | * @author Dmytro Paukov 16 | */ 17 | public class IntegerVectorTest { 18 | 19 | @Test 20 | public void testEqualVectors() { 21 | 22 | // create a combinatorics vector1 (a, b, c) 23 | IntegerVector vector1 = IntegerFactory.createIntegerVector(new int[]{ 24 | 1, 2, 3}); 25 | 26 | assertEquals(3, vector1.getSize()); 27 | assertEquals(false, vector1.hasDuplicates()); 28 | assertEquals(false, vector1.isAllElementsEqual()); 29 | 30 | int[] array2 = new int[]{1, 2, 3}; 31 | 32 | // create a combinatorics vector2 33 | IntegerVector vector2 = IntegerFactory.createIntegerVector(array2); 34 | 35 | assertEquals(vector1, vector2); 36 | } 37 | 38 | @Test 39 | public void testNotEqualVectors() { 40 | 41 | // create an array1 42 | int[] array1 = new int[]{1, 3, 2}; 43 | 44 | // create a combinatorics vector1 45 | IntegerVector vector1 = IntegerFactory.createIntegerVector(array1); 46 | 47 | assertEquals(3, vector1.getSize()); 48 | assertEquals(false, vector1.hasDuplicates()); 49 | 50 | int[] array2 = new int[]{1, 2, 3}; 51 | 52 | // create a combinatorics vector2 53 | IntegerVector vector2 = IntegerFactory.createIntegerVector(array2); 54 | 55 | assertEquals(3, vector2.getSize()); 56 | 57 | assertFalse(array1.equals(array2)); 58 | assertFalse(vector1.equals(vector2)); 59 | } 60 | 61 | @Test 62 | public void testEmptyVectors() { 63 | 64 | // create a combinatorics vector1 65 | IntegerVector vector1 = IntegerFactory.createIntegerVector(); 66 | 67 | assertEquals(0, vector1.getSize()); 68 | assertEquals(false, vector1.hasDuplicates()); 69 | 70 | // create a combinatorics vector2 71 | IntegerVector vector2 = IntegerFactory.createIntegerVector(); 72 | assertEquals(0, vector2.getSize()); 73 | 74 | assertTrue(vector1.equals(vector2)); 75 | } 76 | 77 | @Test 78 | public void testDuplicatesVectors() { 79 | 80 | // create a combinatorics vector (a, b, b, c) 81 | IntegerVector vector = IntegerFactory.createIntegerVector(new int[]{ 82 | 1, 2, 2, 3}); 83 | 84 | assertEquals(4, vector.getSize()); 85 | assertEquals(true, vector.hasDuplicates()); 86 | assertEquals(false, vector.isAllElementsEqual()); 87 | } 88 | 89 | @Test 90 | public void testAllElementsEqualVectors() { 91 | 92 | // create a combinatorics vector (a, a, a, a) 93 | IntegerVector vector = IntegerFactory.createIntegerVector(new int[]{ 94 | 1, 1, 1, 1}); 95 | 96 | assertEquals(4, vector.getSize()); 97 | assertEquals(true, vector.hasDuplicates()); 98 | assertEquals(true, vector.isAllElementsEqual()); 99 | } 100 | 101 | @Test 102 | public void testComplexVectors1() { 103 | 104 | int[] array3 = new int[]{1, 1, 1}; 105 | 106 | int[] array1 = new int[]{1}; 107 | 108 | IntegerVector vector1 = IntegerFactory.createIntegerVector(array1); 109 | 110 | assertEquals(1, vector1.getSize()); 111 | assertEquals(false, vector1.hasDuplicates()); 112 | 113 | IntegerVector vector3 = IntegerFactory.createIntegerVector(array3); 114 | 115 | assertEquals(3, vector3.getSize()); 116 | assertEquals(true, vector3.hasDuplicates()); 117 | 118 | ICombinatoricsVector vectorA = createVector(); 119 | vectorA.addValue(vector1); 120 | vectorA.addValue(vector3); 121 | 122 | assertEquals(2, vectorA.getSize()); 123 | assertEquals(false, vectorA.hasDuplicates()); 124 | 125 | ICombinatoricsVector vectorB = createVector(); 126 | vectorB.addValue(vector3); 127 | vectorB.addValue(vector1); 128 | 129 | assertEquals(2, vectorB.getSize()); 130 | assertEquals(false, vectorB.hasDuplicates()); 131 | 132 | assertEquals(false, vectorA.equals(vectorB)); 133 | 134 | } 135 | 136 | @Test 137 | public void testComplexVectors2() { 138 | 139 | int[] array3 = new int[]{1, 1, 1}; 140 | int[] array2 = new int[]{1, 1}; 141 | int[] array1 = new int[]{1}; 142 | IntegerVector vector1 = IntegerFactory.createIntegerVector(array1); 143 | 144 | assertEquals(1, vector1.getSize()); 145 | assertEquals(false, vector1.hasDuplicates()); 146 | 147 | IntegerVector vector3 = IntegerFactory.createIntegerVector(array3); 148 | 149 | assertEquals(3, vector3.getSize()); 150 | assertEquals(true, vector3.hasDuplicates()); 151 | assertEquals(true, vector3.isAllElementsEqual()); 152 | 153 | IntegerVector vector2 = IntegerFactory.createIntegerVector(array2); 154 | 155 | assertEquals(2, vector2.getSize()); 156 | assertEquals(true, vector2.hasDuplicates()); 157 | 158 | ICombinatoricsVector vectorA = createVector(); 159 | vectorA.addValue(vector1); 160 | vectorA.addValue(vector3); 161 | 162 | assertEquals(2, vectorA.getSize()); 163 | assertEquals(false, vectorA.hasDuplicates()); 164 | 165 | ICombinatoricsVector vectorB = createVector(); 166 | vectorB.addValue(vector2); 167 | vectorB.addValue(vector2); 168 | 169 | assertEquals(2, vectorB.getSize()); 170 | assertEquals(true, vectorB.hasDuplicates()); 171 | 172 | assertEquals(false, vectorA.equals(vectorB)); 173 | 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/subsets/SubSetGenerator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.subsets; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 8 | 9 | import java.util.Iterator; 10 | import org.paukov.combinatorics.CombinatoricsFactory; 11 | import org.paukov.combinatorics.Generator; 12 | import org.paukov.combinatorics.ICombinatoricsVector; 13 | import org.paukov.combinatorics.util.Util; 14 | 15 | /** 16 | * This generator generates all subsets of the specified set/vector. 17 | *

18 | * A set A is a subset of a set B if A is "contained" inside B. A and B may 19 | * coincide. The relationship of one set being a subset of another is called 20 | * inclusion or sometimes containment. 21 | *

22 | * Examples: 23 | *

    24 | *
  • The set (1, 2) is a proper subset of (1, 2, 3). 25 | *
  • Any set is a subset of itself, but not a proper subset. 26 | *
  • The empty set, denoted by (), is also a subset of any given set X. 27 | *
28 | *

29 | * All subsets of (1, 2, 3) are: 30 | *

    31 | *
  1. () 32 | *
  2. (1) 33 | *
  3. (2) 34 | *
  4. (1, 2) 35 | *
  5. (3) 36 | *
  6. (1, 3) 37 | *
  7. (2, 3) 38 | *
  8. (1, 2, 3) 39 | *
40 | *

41 | * And code which generates all subsets of (one, two, three) 42 | *

43 | *

44 | * 45 | *
 46 |  * // Create an initial vector/set
 47 |  * ICombinatoricsVector<String> initialSet = CombinatoricsFactory.createVector(new String[] {
 48 |  * 		"one", "two", "three" });
 49 |  *
 50 |  * // Create an instance of the subset generator
 51 |  * Generator<String> gen = CombinatoricsFactory.createSubSetGenerator(initialSet);
 52 |  *
 53 |  * // Print the subsets
 54 |  * for (ICombinatoricsVector<String> subSet : gen) {
 55 |  * 	System.out.println(subSet);
 56 |  * }
 57 |  * 
58 | * 59 | *
60 | *

61 | * And the result of all 8 possible subsets 62 | *

63 | *

64 | * 65 | *
 66 |  *  CombinatoricsVector=([], size=0)
 67 |  *  CombinatoricsVector=([one], size=1)
 68 |  *  CombinatoricsVector=([two], size=1)
 69 |  *  CombinatoricsVector=([one, two], size=2)
 70 |  *  CombinatoricsVector=([three], size=1)
 71 |  *  CombinatoricsVector=([one, three], size=2)
 72 |  *  CombinatoricsVector=([two, three], size=2)
 73 |  *  CombinatoricsVector=([one, two, three], size=3)
 74 |  * 
75 | * 76 | *
77 | *

78 | * Version 2.0 of the combinatoricslib supports sets with duplicates. For 79 | * example, if the original vector contains duplicates like (a, b, a, c), then 80 | * the result will contain 14 subsets (instead of 16):

81 | * 82 | *
 83 |  * ()
 84 |  * (a)
 85 |  * (b)
 86 |  * (a, b)
 87 |  * (a, a)
 88 |  * (b, a)
 89 |  * (a, b, a)
 90 |  * (c)
 91 |  * (a, c)
 92 |  * (b, c)
 93 |  * (a, b, c)
 94 |  * (a, a, c)
 95 |  * (b, a, c)
 96 |  * (a, b, a, c)
 97 |  * 
98 | * 99 | *
100 | *

101 | * If you still would like to treat the set with duplicates as not identical, 102 | * you should create a generator and set the second parameter of the method 103 | * Factory.createSubSetGenerator() as false. In this 104 | * case all 16 subsets will be generated. 105 | *

106 | * 107 | * Note. If the initial vector contains duplicates then the method 108 | * getNumberOfGeneratedObjects won't be able to return the number 109 | * of the sub sets/lists. It will throw a runtime exception 110 | * 111 | * @param Type of the elements in the set 112 | * @author Dmytro Paukov 113 | * @version 2.0 114 | * @see ICombinatoricsVector 115 | * @see SubSetIterator 116 | */ 117 | public class SubSetGenerator extends Generator { 118 | 119 | protected final boolean _hasDuplicates; 120 | protected final boolean _treatAsIdentical; 121 | 122 | /** 123 | * Core set 124 | */ 125 | protected final ICombinatoricsVector _originalVector; 126 | 127 | /** 128 | * Constructor 129 | * 130 | * @param originalVector Original vector/set 131 | */ 132 | public SubSetGenerator(ICombinatoricsVector originalVector) { 133 | _hasDuplicates = originalVector.hasDuplicates(); 134 | _treatAsIdentical = true; 135 | _originalVector = createVector(originalVector); 136 | } 137 | 138 | /** 139 | * Constructor 140 | * 141 | * @param originalVector Original vector/set 142 | */ 143 | public SubSetGenerator(ICombinatoricsVector originalVector, 144 | boolean treatAsIdentical) { 145 | _hasDuplicates = originalVector.hasDuplicates(); 146 | _treatAsIdentical = treatAsIdentical; 147 | _originalVector = createVector(originalVector); 148 | } 149 | 150 | /** 151 | * Returns the core set 152 | */ 153 | public ICombinatoricsVector getOriginalVector() { 154 | return _originalVector; 155 | } 156 | 157 | /** 158 | * Returns the number of the subsets. If the original set contains 159 | * duplicates this method will throw a runtime exception 160 | */ 161 | public long getNumberOfGeneratedObjects() { 162 | 163 | if (isSubList()) { 164 | throw new RuntimeException("The initial vector has duplicates: " 165 | + _originalVector); 166 | } 167 | 168 | return Util.pow2(_originalVector.getSize()); 169 | } 170 | 171 | /** 172 | * Creates the iterator over the all subsets 173 | */ 174 | @Override 175 | public Iterator> iterator() { 176 | if (isSubList()) { 177 | return new SubListIterator(this); 178 | } else { 179 | return new SubSetIterator(this); 180 | } 181 | } 182 | 183 | protected boolean isSubList() { 184 | return (_treatAsIdentical && _hasDuplicates); 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/CombinatoricsVectorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.junit.Assert.assertFalse; 9 | import static org.junit.Assert.assertNotEquals; 10 | import static org.junit.Assert.assertTrue; 11 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import org.junit.Test; 16 | 17 | /** 18 | * @author Dmytro Paukov 19 | */ 20 | public class CombinatoricsVectorTest { 21 | 22 | @Test 23 | public void testEqualVectors() { 24 | // create a combinatorics vector1 (a, b, c) 25 | ICombinatoricsVector vector1 = createVector("a", "b", "c"); 26 | 27 | assertEquals(3, vector1.getSize()); 28 | assertFalse(vector1.hasDuplicates()); 29 | assertFalse(vector1.isAllElementsEqual()); 30 | 31 | List array2 = new ArrayList(); 32 | array2.add("a"); 33 | array2.add("b"); 34 | array2.add("c"); 35 | 36 | // create a combinatorics vector2 37 | ICombinatoricsVector vector2 = createVector(array2); 38 | 39 | assertEquals(vector1, vector2); 40 | } 41 | 42 | @Test 43 | public void testNotEqualVectors() { 44 | // create an array1 45 | List array1 = new ArrayList(); 46 | array1.add("a"); 47 | array1.add("c"); 48 | array1.add("b"); 49 | 50 | // create a combinatorics vector1 51 | ICombinatoricsVector vector1 = createVector(array1); 52 | 53 | assertEquals(3, vector1.getSize()); 54 | assertFalse(vector1.hasDuplicates()); 55 | 56 | List array2 = new ArrayList(); 57 | array2.add("a"); 58 | array2.add("b"); 59 | array2.add("c"); 60 | 61 | // create a combinatorics vector2 62 | ICombinatoricsVector vector2 = createVector(array2); 63 | 64 | assertEquals(3, vector2.getSize()); 65 | 66 | assertNotEquals(array1, array2); 67 | assertNotEquals(vector1, vector2); 68 | } 69 | 70 | @Test 71 | public void testEmptyVectors() { 72 | // create a combinatorics vector1 73 | ICombinatoricsVector vector1 = createVector(); 74 | 75 | assertEquals(0, vector1.getSize()); 76 | assertFalse(vector1.hasDuplicates()); 77 | 78 | // create a combinatorics vector2 79 | ICombinatoricsVector vector2 = createVector(); 80 | 81 | assertEquals(0, vector2.getSize()); 82 | 83 | assertEquals(vector1, vector2); 84 | } 85 | 86 | @Test 87 | public void testDuplicatesVectors() { 88 | // create a combinatorics vector (a, b, b, c) 89 | ICombinatoricsVector vector = createVector("a", "b", "b", "c"); 90 | 91 | assertEquals(4, vector.getSize()); 92 | assertTrue(vector.hasDuplicates()); 93 | assertFalse(vector.isAllElementsEqual()); 94 | } 95 | 96 | @Test 97 | public void testAllElementsEqualVectors() { 98 | // create a combinatorics vector (a, a, a, a) 99 | ICombinatoricsVector vector = createVector("a", "a", "a", "a"); 100 | 101 | assertEquals(4, vector.getSize()); 102 | assertTrue(vector.hasDuplicates()); 103 | assertTrue(vector.isAllElementsEqual()); 104 | } 105 | 106 | @Test 107 | public void testComplexVectors1() { 108 | List array3 = new ArrayList(); 109 | array3.add("a"); 110 | array3.add("a"); 111 | array3.add("a"); 112 | 113 | List array1 = new ArrayList(); 114 | array1.add("a"); 115 | 116 | ICombinatoricsVector vector1 = createVector(array1); 117 | 118 | assertEquals(1, vector1.getSize()); 119 | assertFalse(vector1.hasDuplicates()); 120 | 121 | ICombinatoricsVector vector3 = createVector(array3); 122 | 123 | assertEquals(3, vector3.getSize()); 124 | assertTrue(vector3.hasDuplicates()); 125 | 126 | ICombinatoricsVector> vectorA = createVector(); 127 | vectorA.addValue(vector1); 128 | vectorA.addValue(vector3); 129 | 130 | assertEquals(2, vectorA.getSize()); 131 | assertFalse(vectorA.hasDuplicates()); 132 | 133 | ICombinatoricsVector> vectorB = createVector(); 134 | vectorB.addValue(vector3); 135 | vectorB.addValue(vector1); 136 | 137 | assertEquals(2, vectorB.getSize()); 138 | assertFalse(vectorB.hasDuplicates()); 139 | 140 | assertNotEquals(vectorA, vectorB); 141 | } 142 | 143 | @Test 144 | public void testComplexVectors2() { 145 | List array3 = new ArrayList<>(); 146 | array3.add("a"); 147 | array3.add("a"); 148 | array3.add("a"); 149 | 150 | List array1 = new ArrayList<>(); 151 | array1.add("a"); 152 | 153 | List array2 = new ArrayList<>(); 154 | array2.add("a"); 155 | array2.add("a"); 156 | 157 | ICombinatoricsVector vector1 = createVector(array1); 158 | 159 | assertEquals(1, vector1.getSize()); 160 | assertFalse(vector1.hasDuplicates()); 161 | 162 | ICombinatoricsVector vector3 = createVector(array3); 163 | 164 | assertEquals(3, vector3.getSize()); 165 | assertTrue(vector3.hasDuplicates()); 166 | assertTrue(vector3.isAllElementsEqual()); 167 | 168 | ICombinatoricsVector vector2 = createVector(array2); 169 | 170 | assertEquals(2, vector2.getSize()); 171 | assertTrue(vector2.hasDuplicates()); 172 | 173 | ICombinatoricsVector> vectorA = createVector(); 174 | vectorA.addValue(vector1); 175 | vectorA.addValue(vector3); 176 | 177 | assertEquals(2, vectorA.getSize()); 178 | assertFalse(vectorA.hasDuplicates()); 179 | 180 | ICombinatoricsVector> vectorB = createVector(); 181 | vectorB.addValue(vector2); 182 | vectorB.addValue(vector2); 183 | 184 | assertEquals(2, vectorB.getSize()); 185 | assertTrue(vectorB.hasDuplicates()); 186 | 187 | assertNotEquals(vectorA, vectorB); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/composition/IntegerCompositionTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.composition; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.paukov.combinatorics.IntegerFactory.createIntegerCompositionGenerator; 9 | 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import org.junit.Test; 13 | import org.paukov.combinatorics.IGenerator; 14 | import org.paukov.combinatorics.IntegerGenerator; 15 | import org.paukov.combinatorics.IntegerVector; 16 | 17 | /** 18 | * @author Dmytro Paukov 19 | */ 20 | public class IntegerCompositionTest { 21 | 22 | @Test 23 | public void simpleFiveComposition() { 24 | 25 | IGenerator compositionGenerator = createIntegerCompositionGenerator(5); 26 | Iterator compositionIterator = compositionGenerator.iterator(); 27 | 28 | System.out.println("Number of compositions is: " 29 | + compositionGenerator.getNumberOfGeneratedObjects()); 30 | assertEquals(16, compositionGenerator.getNumberOfGeneratedObjects()); 31 | 32 | while (compositionIterator.hasNext()) { 33 | compositionIterator.next(); 34 | System.out.println(compositionIterator); 35 | } 36 | 37 | List list = compositionGenerator.generateAllObjects(); 38 | 39 | assertEquals(5, compositionGenerator.getOriginalVector().getValue(0)); 40 | 41 | assertEquals(16, list.size()); 42 | 43 | assertEquals("IntegerVector=([5], size=1)", list.get(0).toString()); 44 | assertEquals("IntegerVector=([1, 4], size=2)", list.get(1).toString()); 45 | assertEquals("IntegerVector=([2, 3], size=2)", list.get(2).toString()); 46 | assertEquals("IntegerVector=([1, 1, 3], size=3)", list.get(3) 47 | .toString()); 48 | assertEquals("IntegerVector=([3, 2], size=2)", list.get(4).toString()); 49 | assertEquals("IntegerVector=([1, 2, 2], size=3)", list.get(5) 50 | .toString()); 51 | assertEquals("IntegerVector=([2, 1, 2], size=3)", list.get(6) 52 | .toString()); 53 | 54 | assertEquals("IntegerVector=([1, 1, 1, 2], size=4)", list.get(7) 55 | .toString()); 56 | assertEquals("IntegerVector=([4, 1], size=2)", list.get(8).toString()); 57 | assertEquals("IntegerVector=([1, 3, 1], size=3)", list.get(9) 58 | .toString()); 59 | assertEquals("IntegerVector=([2, 2, 1], size=3)", list.get(10) 60 | .toString()); 61 | assertEquals("IntegerVector=([1, 1, 2, 1], size=4)", list.get(11) 62 | .toString()); 63 | assertEquals("IntegerVector=([3, 1, 1], size=3)", list.get(12) 64 | .toString()); 65 | assertEquals("IntegerVector=([1, 2, 1, 1], size=4)", list.get(13) 66 | .toString()); 67 | 68 | assertEquals("IntegerVector=([2, 1, 1, 1], size=4)", list.get(14) 69 | .toString()); 70 | assertEquals("IntegerVector=([1, 1, 1, 1, 1], size=5)", list.get(15) 71 | .toString()); 72 | } 73 | 74 | @Test 75 | public void simpleFiveCompositionRange() { 76 | 77 | IntegerGenerator compositionGenerator = createIntegerCompositionGenerator(5); 78 | 79 | System.out.println("Number of compositions is: " 80 | + compositionGenerator.getNumberOfGeneratedObjects()); 81 | assertEquals(16, compositionGenerator.getNumberOfGeneratedObjects()); 82 | 83 | List list = compositionGenerator.generateObjectsRange(5, 84 | 7); 85 | 86 | assertEquals(3, list.size()); 87 | 88 | assertEquals("IntegerVector=([3, 2], size=2)", list.get(0).toString()); 89 | assertEquals("IntegerVector=([1, 2, 2], size=3)", list.get(1) 90 | .toString()); 91 | assertEquals("IntegerVector=([2, 1, 2], size=3)", list.get(2) 92 | .toString()); 93 | } 94 | 95 | @Test 96 | public void simpleOneComposition() { 97 | 98 | IntegerGenerator compositionGenerator = createIntegerCompositionGenerator(1); 99 | Iterator compositionIterator = compositionGenerator.iterator(); 100 | 101 | System.out.println("Number of compositions is: " 102 | + compositionGenerator.getNumberOfGeneratedObjects()); 103 | assertEquals(1, compositionGenerator.getNumberOfGeneratedObjects()); 104 | 105 | while (compositionIterator.hasNext()) { 106 | compositionIterator.next(); 107 | System.out.println(compositionIterator); 108 | } 109 | 110 | List list = compositionGenerator.generateAllObjects(); 111 | 112 | assertEquals(1, list.size()); 113 | 114 | assertEquals("IntegerVector=([1], size=1)", list.get(0).toString()); 115 | 116 | } 117 | 118 | @Test 119 | public void simpleTwoComposition() { 120 | 121 | IntegerGenerator compositionGenerator = createIntegerCompositionGenerator(2); 122 | Iterator compositionIterator = compositionGenerator.iterator(); 123 | 124 | System.out.println("Number of compositions is: " 125 | + compositionGenerator.getNumberOfGeneratedObjects()); 126 | assertEquals(2, compositionGenerator.getNumberOfGeneratedObjects()); 127 | 128 | while (compositionIterator.hasNext()) { 129 | compositionIterator.next(); 130 | System.out.println(compositionIterator); 131 | } 132 | 133 | List list = compositionGenerator.generateAllObjects(); 134 | 135 | assertEquals(2, list.size()); 136 | 137 | assertEquals("IntegerVector=([2], size=1)", list.get(0).toString()); 138 | assertEquals("IntegerVector=([1, 1], size=2)", list.get(1).toString()); 139 | 140 | } 141 | 142 | @Test 143 | public void simpleZeroComposition() { 144 | 145 | IntegerGenerator compositionGenerator = createIntegerCompositionGenerator(0); 146 | Iterator compositionIterator = compositionGenerator.iterator(); 147 | 148 | System.out.println("Number of compositions is: " 149 | + compositionGenerator.getNumberOfGeneratedObjects()); 150 | assertEquals(1, compositionGenerator.getNumberOfGeneratedObjects()); 151 | 152 | while (compositionIterator.hasNext()) { 153 | compositionIterator.next(); 154 | System.out.println(compositionIterator); 155 | } 156 | 157 | List list = compositionGenerator.generateAllObjects(); 158 | 159 | assertEquals(1, list.size()); 160 | 161 | assertEquals("IntegerVector=([0], size=1)", list.get(0).toString()); 162 | 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/IntegerVector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics; 6 | 7 | import java.util.Arrays; 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | 11 | /** 12 | * This class represents a simple vector of elements of type int 13 | * 14 | * @author Dmytro Paukov 15 | * @version 2.0 16 | * @see IntegerGenerator 17 | * @see IntegerFactory 18 | */ 19 | public class IntegerVector { 20 | 21 | protected final int[] _vector; 22 | 23 | /** 24 | * Default constructor creates an empty vector 25 | *

26 | * Notes: Use the factory method 27 | * IntegerFactory.createIntegerVector() to create an empty 28 | * vector 29 | * 30 | * @see IntegerFactory 31 | */ 32 | public IntegerVector() { 33 | this(0); 34 | } 35 | 36 | /** 37 | * Default constructor creates the empty vector 38 | *

39 | * Notes: Use the factory method 40 | * IntegerFactory.createIntegerVector() to create an empty 41 | * vector 42 | * 43 | * @see IntegerFactory 44 | */ 45 | public IntegerVector(int size) { 46 | _vector = new int[size]; 47 | } 48 | 49 | /** 50 | * Constructor from an array 51 | *

52 | * Notes: Use the factory method 53 | * IntegerFactory.createIntegerVector() to create a vector from 54 | * an array 55 | * 56 | * @param array Initial array to initialize the created vector 57 | * @see IntegerFactory 58 | */ 59 | public IntegerVector(int[] array, int len) { 60 | _vector = new int[len]; 61 | System.arraycopy(array, 0, _vector, 0, len); 62 | } 63 | 64 | /** 65 | * Constructor from an integer array 66 | *

67 | * Notes: Use the factory method 68 | * IntegerFactory.createIntegerVector() to create a vector from 69 | * an array 70 | * 71 | * @param array Initial array to initialize the created vector 72 | * @see IntegerFactory 73 | */ 74 | public IntegerVector(int[] array) { 75 | this(array, array.length); 76 | } 77 | 78 | /** 79 | * Copy constructor 80 | *

81 | * Notes: Use the factory method 82 | * IntegerFactory.createIntegerVector() to create a vector from 83 | * another vector 84 | * 85 | * @param vector Initial vector to initialize the created vector 86 | */ 87 | public IntegerVector(IntegerVector vector) { 88 | _vector = new int[vector.getSize()]; 89 | System.arraycopy(vector._vector, 0, _vector, 0, vector.getSize()); 90 | } 91 | 92 | /** 93 | * Sets the value of the index-element 94 | */ 95 | public void setValue(int index, int value) { 96 | _vector[index] = value; 97 | } 98 | 99 | /** 100 | * Gets the value of the given index 101 | * 102 | * @return The value of the index element 103 | */ 104 | public int getValue(int index) { 105 | return _vector[index]; 106 | } 107 | 108 | /** 109 | * Returns the size of the vector 110 | * 111 | * @return The size of the vector 112 | */ 113 | public int getSize() { 114 | if (_vector == null) { 115 | return 0; 116 | } 117 | return _vector.length; 118 | } 119 | 120 | /** 121 | * This method detects duplicates in the vector 122 | * 123 | * @return true if the vector has duplicates, otherwise false 124 | */ 125 | public boolean hasDuplicates() { 126 | if (_vector.length <= 1) { 127 | return false; 128 | } 129 | Set set = new HashSet(); 130 | for (int i = 0; i < _vector.length; i++) { 131 | set.add(_vector[i]); 132 | } 133 | return set.size() < _vector.length; 134 | } 135 | 136 | /** 137 | * This method detects if the vector's elements are equal. For example, this 138 | * method returns true for a vector (a, a, a) and false for a vector (a, b, 139 | * a) 140 | * 141 | * @return True if the vector's elements are equal 142 | */ 143 | public boolean isAllElementsEqual() { 144 | if (_vector.length == 0) { 145 | return false; 146 | } 147 | if (_vector.length == 1) { 148 | return true; 149 | } 150 | for (int i = 0; i < _vector.length - 1; i++) { 151 | if (_vector[i] != _vector[i + 1]) { 152 | return false; 153 | } 154 | } 155 | return true; 156 | } 157 | 158 | /** 159 | * Returns vector as a list of elements 160 | * 161 | * @return List of all elements 162 | */ 163 | public int[] getVector() { 164 | return _vector; 165 | } 166 | 167 | /** 168 | * Hash code of the vector 169 | * 170 | * @see java.lang.Object#hashCode() 171 | */ 172 | public int hashCode() { 173 | final int prime = 31; 174 | int result = 1; 175 | result = prime * result 176 | + ((_vector == null) ? 0 : Arrays.hashCode(_vector)); 177 | return result; 178 | } 179 | 180 | /** 181 | * Equals 182 | * 183 | * @see java.lang.Object#equals(java.lang.Object) 184 | */ 185 | @Override 186 | public boolean equals(Object obj) { 187 | if (this == obj) { 188 | return true; 189 | } 190 | if (obj == null) { 191 | return false; 192 | } 193 | if (getClass() != obj.getClass()) { 194 | return false; 195 | } 196 | IntegerVector other = (IntegerVector) obj; 197 | if (_vector == other._vector) { 198 | return true; 199 | } 200 | if (_vector == null) { 201 | return false; 202 | } 203 | if (other._vector == null) { 204 | return false; 205 | } 206 | 207 | if (_vector.length != other._vector.length) { 208 | return false; 209 | } 210 | for (int i = 0; i < _vector.length; i++) { 211 | if (_vector[i] != other._vector[i]) { 212 | return false; 213 | } 214 | } 215 | 216 | return true; 217 | } 218 | 219 | /** 220 | * Returns vector as a string 221 | * 222 | * @see java.lang.Object#toString() 223 | */ 224 | @Override 225 | public String toString() { 226 | StringBuilder sb = new StringBuilder(); 227 | sb.append("IntegerVector=(["); 228 | for (int i = 0; i < _vector.length; i++) { 229 | sb.append(_vector[i]); 230 | if (i < _vector.length - 1) { 231 | sb.append(", "); 232 | } 233 | } 234 | sb.append("], size=").append(getSize()).append(")"); 235 | return sb.toString(); 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/composition/CompositionTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.composition; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.paukov.combinatorics.CombinatoricsFactory.createCompositionGenerator; 9 | 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import org.junit.Test; 13 | import org.paukov.combinatorics.Generator; 14 | import org.paukov.combinatorics.ICombinatoricsVector; 15 | 16 | /** 17 | * @author Dmytro Paukov 18 | */ 19 | public class CompositionTest { 20 | 21 | @Test 22 | public void simpleFiveComposition() { 23 | 24 | Generator compositionGenerator = createCompositionGenerator(5); 25 | Iterator> compositionIterator = compositionGenerator.iterator(); 26 | 27 | System.out.println("Number of compositions is: " 28 | + compositionGenerator.getNumberOfGeneratedObjects()); 29 | assertEquals(16, compositionGenerator.getNumberOfGeneratedObjects()); 30 | 31 | while (compositionIterator.hasNext()) { 32 | compositionIterator.next(); 33 | System.out.println(compositionIterator); 34 | } 35 | 36 | List> list = compositionGenerator.generateAllObjects(); 37 | 38 | assertEquals(5, compositionGenerator.getOriginalVector().getValue(0).intValue()); 39 | 40 | assertEquals(16, list.size()); 41 | 42 | assertEquals("CombinatoricsVector=([5], size=1)", list.get(0) 43 | .toString()); 44 | assertEquals("CombinatoricsVector=([1, 4], size=2)", list.get(1) 45 | .toString()); 46 | assertEquals("CombinatoricsVector=([2, 3], size=2)", list.get(2) 47 | .toString()); 48 | assertEquals("CombinatoricsVector=([1, 1, 3], size=3)", list.get(3) 49 | .toString()); 50 | assertEquals("CombinatoricsVector=([3, 2], size=2)", list.get(4) 51 | .toString()); 52 | assertEquals("CombinatoricsVector=([1, 2, 2], size=3)", list.get(5) 53 | .toString()); 54 | assertEquals("CombinatoricsVector=([2, 1, 2], size=3)", list.get(6) 55 | .toString()); 56 | 57 | assertEquals("CombinatoricsVector=([1, 1, 1, 2], size=4)", list.get(7) 58 | .toString()); 59 | assertEquals("CombinatoricsVector=([4, 1], size=2)", list.get(8) 60 | .toString()); 61 | assertEquals("CombinatoricsVector=([1, 3, 1], size=3)", list.get(9) 62 | .toString()); 63 | assertEquals("CombinatoricsVector=([2, 2, 1], size=3)", list.get(10) 64 | .toString()); 65 | assertEquals("CombinatoricsVector=([1, 1, 2, 1], size=4)", list.get(11) 66 | .toString()); 67 | assertEquals("CombinatoricsVector=([3, 1, 1], size=3)", list.get(12) 68 | .toString()); 69 | assertEquals("CombinatoricsVector=([1, 2, 1, 1], size=4)", list.get(13) 70 | .toString()); 71 | 72 | assertEquals("CombinatoricsVector=([2, 1, 1, 1], size=4)", list.get(14) 73 | .toString()); 74 | assertEquals("CombinatoricsVector=([1, 1, 1, 1, 1], size=5)", 75 | list.get(15).toString()); 76 | } 77 | 78 | @Test 79 | public void simpleFiveCompositionRange() { 80 | 81 | Generator compositionGenerator = createCompositionGenerator(5); 82 | 83 | System.out.println("Number of compositions is: " 84 | + compositionGenerator.getNumberOfGeneratedObjects()); 85 | assertEquals(16, compositionGenerator.getNumberOfGeneratedObjects()); 86 | 87 | List> list = compositionGenerator 88 | .generateObjectsRange(5, 7); 89 | 90 | assertEquals(3, list.size()); 91 | 92 | assertEquals("CombinatoricsVector=([3, 2], size=2)", list.get(0) 93 | .toString()); 94 | assertEquals("CombinatoricsVector=([1, 2, 2], size=3)", list.get(1) 95 | .toString()); 96 | assertEquals("CombinatoricsVector=([2, 1, 2], size=3)", list.get(2) 97 | .toString()); 98 | } 99 | 100 | @Test 101 | public void simpleOneComposition() { 102 | 103 | Generator compositionGenerator = createCompositionGenerator(1); 104 | Iterator> compositionIterator = compositionGenerator 105 | .iterator(); 106 | 107 | System.out.println("Number of compositions is: " 108 | + compositionGenerator.getNumberOfGeneratedObjects()); 109 | assertEquals(1, compositionGenerator.getNumberOfGeneratedObjects()); 110 | 111 | while (compositionIterator.hasNext()) { 112 | compositionIterator.next(); 113 | System.out.println(compositionIterator); 114 | } 115 | 116 | List> list = compositionGenerator 117 | .generateAllObjects(); 118 | 119 | assertEquals(1, list.size()); 120 | 121 | assertEquals("CombinatoricsVector=([1], size=1)", list.get(0) 122 | .toString()); 123 | 124 | } 125 | 126 | @Test 127 | public void simpleTwoComposition() { 128 | 129 | Generator compositionGenerator = createCompositionGenerator(2); 130 | Iterator> compositionIterator = compositionGenerator 131 | .iterator(); 132 | 133 | System.out.println("Number of compositions is: " 134 | + compositionGenerator.getNumberOfGeneratedObjects()); 135 | assertEquals(2, compositionGenerator.getNumberOfGeneratedObjects()); 136 | 137 | while (compositionIterator.hasNext()) { 138 | compositionIterator.next(); 139 | System.out.println(compositionIterator); 140 | } 141 | 142 | List> list = compositionGenerator 143 | .generateAllObjects(); 144 | 145 | assertEquals(2, list.size()); 146 | 147 | assertEquals("CombinatoricsVector=([2], size=1)", list.get(0) 148 | .toString()); 149 | assertEquals("CombinatoricsVector=([1, 1], size=2)", list.get(1) 150 | .toString()); 151 | 152 | } 153 | 154 | @Test 155 | public void simpleZeroComposition() { 156 | 157 | Generator compositionGenerator = createCompositionGenerator(0); 158 | Iterator> compositionIterator = compositionGenerator 159 | .iterator(); 160 | 161 | System.out.println("Number of compositions is: " 162 | + compositionGenerator.getNumberOfGeneratedObjects()); 163 | assertEquals(1, compositionGenerator.getNumberOfGeneratedObjects()); 164 | 165 | while (compositionIterator.hasNext()) { 166 | compositionIterator.next(); 167 | System.out.println(compositionIterator); 168 | } 169 | 170 | List> list = compositionGenerator 171 | .generateAllObjects(); 172 | 173 | assertEquals(1, list.size()); 174 | 175 | assertEquals("CombinatoricsVector=([0], size=1)", list.get(0) 176 | .toString()); 177 | 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/util/ComplexCombinationIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.util; 6 | 7 | import static org.paukov.combinatorics.CombinatoricsFactory.createMultiCombinationGenerator; 8 | import static org.paukov.combinatorics.CombinatoricsFactory.createPermutationGenerator; 9 | import static org.paukov.combinatorics.CombinatoricsFactory.createSubSetGenerator; 10 | import static org.paukov.combinatorics.CombinatoricsFactory.createVector; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Iterator; 14 | import java.util.LinkedHashSet; 15 | import java.util.List; 16 | import java.util.Set; 17 | import org.paukov.combinatorics.Generator; 18 | import org.paukov.combinatorics.ICombinatoricsVector; 19 | 20 | 21 | /** 22 | * Iterator over the all complex combinations 23 | * 24 | * @author Dmytro Paukov 25 | * @version 2.0 26 | * @see ComplexCombinationGenerator 27 | */ 28 | class ComplexCombinationIterator 29 | implements 30 | Iterator>> { 31 | 32 | /** 33 | * Generator 34 | */ 35 | final ComplexCombinationGenerator _generator; 36 | 37 | /** 38 | * Current combination 39 | */ 40 | ICombinatoricsVector> _currentComplexCombination = null; 41 | 42 | /** 43 | * Current index of the combination 44 | */ 45 | long _currentIndex = 0; 46 | 47 | /** 48 | * The set of the generated combinations 49 | */ 50 | Set>> _resultSet = new LinkedHashSet>>(); 51 | 52 | /** 53 | * The iterator over the result combinations 54 | */ 55 | Iterator>> _resultIterator = null; 56 | 57 | /** 58 | * Constructor 59 | * 60 | * @param generator Generator of the complex combinations 61 | */ 62 | public ComplexCombinationIterator(ComplexCombinationGenerator generator) { 63 | _generator = generator; 64 | init(); 65 | } 66 | 67 | /** 68 | * Initialization of the iteration process 69 | */ 70 | private void init() { 71 | 72 | // 1. Generate all permutations from the original list 73 | Generator permutationGenerator = createPermutationGenerator(_generator.getOriginalVector() 74 | .getValue(0)); 75 | List> permutationsList = permutationGenerator 76 | .generateAllObjects(); 77 | 78 | // 2. Generate all subsets of the original list 79 | Generator subSetGenerator = createSubSetGenerator( 80 | _generator.getOriginalVector().getValue(0)); 81 | List> allSubsetsList = subSetGenerator.generateAllObjects(); 82 | 83 | // If empty set has to be excluded, remove it from the sub sets 84 | if (_generator.excludeEmptySet()) { 85 | allSubsetsList.remove(createVector()); 86 | } 87 | 88 | // 3.1 Create a vector of all subsets 89 | ICombinatoricsVector> allSubsetsVector = createVector(allSubsetsList); 90 | 91 | // 3.2 Create a simple generator to get all n-combination of the subsets 92 | Generator> combinationGenerator = createMultiCombinationGenerator( 93 | allSubsetsVector, 94 | _generator.getCombinationLength()); 95 | 96 | // 3.3 Get an iterator 97 | Iterator>> combinationIterator = combinationGenerator 98 | .iterator(); 99 | 100 | // 3.4 Create an intermediate combinations list to store the candidates 101 | List>> intermediateCombinations = new ArrayList<>(); 102 | 103 | // 3.5 Search the combinations which are contained in the permutations 104 | while (combinationIterator.hasNext()) { 105 | 106 | // 3.5.1 Get a combination 107 | ICombinatoricsVector> combination = combinationIterator.next(); 108 | 109 | /** 110 | * 3.5.2 Construct a list/combinatorial vector of all elements from 111 | * the combination. 112 | */ 113 | 114 | // 3.5.2.1 Put the first element into the list 115 | List list = new ArrayList<>(); 116 | if (combination.getSize() > 0) { 117 | list.addAll(combination.getValue(0).getVector()); 118 | } 119 | 120 | // 3.5.2.2 Add all other elements into the list 121 | for (int index = 1; index < combination.getSize(); index++) { 122 | list.addAll(combination.getValue(index).getVector()); 123 | } 124 | 125 | // 3.5.2.3 Create a vector which contains all elements from the 126 | // combination 127 | ICombinatoricsVector vector = createVector(list); 128 | 129 | // 3.5.3 Add the combination into the intermediate result if the 130 | // constructed vector exists in the permutations list 131 | if (permutationsList.contains(vector)) { 132 | 133 | if (!intermediateCombinations.contains(combination)) { 134 | intermediateCombinations.add(combination); 135 | } 136 | } 137 | } 138 | 139 | // If order is not important, the intermediate combinations are the 140 | // final result 141 | // otherwise we need generate permutations 142 | if (!_generator.isOrderImportant()) { 143 | _resultSet.addAll(intermediateCombinations); 144 | } else { 145 | 146 | // 4. Generate permutations for each found combination and add them 147 | // into the final result list 148 | for (ICombinatoricsVector> combination : intermediateCombinations) { 149 | 150 | // 4.1 Create a permutation generator for each intermediate 151 | // combination 152 | Generator> permutationGen = createPermutationGenerator( 153 | createVector(combination)); 154 | 155 | // 4.2 Generate all permutations 156 | List>> permutations = permutationGen 157 | .generateAllObjects(); 158 | 159 | // 4.3 Add then into the final result list 160 | _resultSet.addAll(permutations); 161 | } 162 | } 163 | 164 | _resultIterator = _resultSet.iterator(); 165 | _currentIndex = 0; 166 | } 167 | 168 | /** 169 | * Returns true if all combinations were iterated, otherwise false 170 | */ 171 | @Override 172 | public boolean hasNext() { 173 | return _resultIterator.hasNext(); 174 | } 175 | 176 | /** 177 | * Moves to the next combination 178 | */ 179 | @Override 180 | public ICombinatoricsVector> next() { 181 | _currentIndex++; 182 | 183 | _currentComplexCombination = _resultIterator.next(); 184 | 185 | return _currentComplexCombination; 186 | } 187 | 188 | @Override 189 | public void remove() { 190 | throw new UnsupportedOperationException(); 191 | } 192 | 193 | /** 194 | * Returns the current combination as a string 195 | * 196 | * @see java.lang.Object#toString() 197 | */ 198 | @Override 199 | public String toString() { 200 | return "ComplexeCombinationIterator=[#" + _currentIndex + ", " 201 | + _currentComplexCombination + "]"; 202 | } 203 | 204 | } -------------------------------------------------------------------------------- /src/main/java/org/paukov/combinatorics/CombinatoricsVector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library Copyright 2012 Dmytro Paukov d.paukov@gmail.com 3 | */ 4 | package org.paukov.combinatorics; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collection; 8 | import java.util.Collections; 9 | import java.util.HashSet; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import java.util.Set; 13 | 14 | /** 15 | * This class represents a simple vector of element's type T. 16 | * 17 | * @param Type of the elements 18 | * @author Dmytro Paukov 19 | * @version 2.0 20 | * @see Generator 21 | * @see Iterator 22 | * @see CombinatoricsFactory 23 | */ 24 | public class CombinatoricsVector implements ICombinatoricsVector { 25 | 26 | protected final List _vector; 27 | 28 | /** 29 | * Default constructor that creates an empty vector. 30 | *

31 | * Notes: Use the factory method CombinatoricsFactory.createVector() to create an 32 | * empty vector. 33 | */ 34 | public CombinatoricsVector() { 35 | _vector = new ArrayList<>(); 36 | } 37 | 38 | /** 39 | * Constructor from a collection. 40 | *

41 | * Notes: Use the factory method CombinatoricsFactory.createVector() to create a 42 | * vector from a collection. 43 | * 44 | * @param vector Initial collection to initialize the created vector. 45 | */ 46 | public CombinatoricsVector(Collection vector) { 47 | _vector = new ArrayList<>(vector.size()); 48 | _vector.addAll(vector); 49 | } 50 | 51 | /** 52 | * Constructor from an array. 53 | *

54 | * Notes: Use the factory method CombinatoricsFactory.createVector() to create a 55 | * vector from an array. 56 | * 57 | * @param array Initial array to initialize the created vector. 58 | */ 59 | public CombinatoricsVector(T... array) { 60 | _vector = new ArrayList<>(array.length); 61 | Collections.addAll(_vector, array); 62 | } 63 | 64 | /** 65 | * Copy constructor 66 | *

67 | *

68 | * Notes: Use the factory method CombinatoricsFactory.createVector() to create a 69 | * vector from another vector. 70 | * 71 | * @param vector Initial combinatorics vector to initialize the created vector. 72 | */ 73 | public CombinatoricsVector(ICombinatoricsVector vector) { 74 | _vector = new ArrayList<>(vector.getSize()); 75 | _vector.addAll(vector.getVector()); 76 | } 77 | 78 | /** 79 | * Sets value to position index. If the index is out of bounds the value will be 80 | * added at the end of the vector. 81 | * 82 | * @param index Position of element. 83 | * @param value Value of the element to be set. 84 | */ 85 | @Override 86 | public void setValue(int index, T value) { 87 | if (index < _vector.size()) { 88 | _vector.set(index, value); 89 | } else { 90 | _vector.add(index, value); 91 | } 92 | } 93 | 94 | /** 95 | * Adds value to this vector. 96 | * 97 | * @param value Value of the element to be added. 98 | */ 99 | @Override 100 | public boolean addValue(T value) { 101 | return _vector.add(value); 102 | } 103 | 104 | /** 105 | * Returns value of the index-element. 106 | * 107 | * @param index The position of the element (Index of the element). 108 | * @return Value of the element. 109 | */ 110 | @Override 111 | public T getValue(int index) { 112 | return _vector.get(index); 113 | } 114 | 115 | /** 116 | * Returns the size of the vector. 117 | */ 118 | @Override 119 | public int getSize() { 120 | if (_vector == null) { 121 | return 0; 122 | } 123 | return _vector.size(); 124 | } 125 | 126 | /** 127 | * This method detects duplicates in the vector. 128 | * 129 | * @return true if the vector has duplicates, otherwise false. 130 | */ 131 | @Override 132 | public boolean hasDuplicates() { 133 | if (_vector.size() <= 1) { 134 | return false; 135 | } 136 | Set set = new HashSet<>(_vector); 137 | return set.size() < _vector.size(); 138 | } 139 | 140 | /** 141 | * This method calculates the count of duplicates of a given value. 142 | * 143 | * @return Number of the duplicates within the vector. 144 | */ 145 | @Override 146 | public int countElements(T value) { 147 | if (_vector.size() == 0) { 148 | return 0; 149 | } 150 | 151 | int count = 0; 152 | for (T element : _vector) { 153 | if (element == value || (element != null && element.equals(value))) { 154 | count++; 155 | } 156 | } 157 | return count; 158 | } 159 | 160 | /** 161 | * This method detects if the vector contains a given value. 162 | * 163 | * @return true if the vector contains the value, otherwise false. 164 | */ 165 | @Override 166 | public boolean contains(T value) { 167 | return _vector.contains(value); 168 | } 169 | 170 | /** 171 | * This method detects if the vector's elements are equal. For example, this method returns true 172 | * for a vector (a, a, a) and false for a vector (a, b, a). 173 | * 174 | * @return True if the vector's elements are equal. 175 | */ 176 | @Override 177 | public boolean isAllElementsEqual() { 178 | if (_vector.size() == 0) { 179 | return false; 180 | } 181 | if (_vector.size() == 1) { 182 | return true; 183 | } 184 | Set set = new HashSet<>(_vector); 185 | return set.size() == 1; 186 | } 187 | 188 | /** 189 | * Returns this vector as a list. 190 | */ 191 | @Override 192 | public List getVector() { 193 | return _vector; 194 | } 195 | 196 | /** 197 | * Hash code of the current vector. 198 | * 199 | * @see java.lang.Object#hashCode() 200 | */ 201 | @Override 202 | public int hashCode() { 203 | final int prime = 31; 204 | int result = 1; 205 | result = prime * result + ((_vector == null) ? 0 : _vector.hashCode()); 206 | return result; 207 | } 208 | 209 | /** 210 | * Indicates whether some other object is "equal to" this one. 211 | * 212 | * @see java.lang.Object#equals(java.lang.Object) 213 | */ 214 | @Override 215 | public boolean equals(Object obj) { 216 | if (this == obj) { 217 | return true; 218 | } 219 | if (obj == null) { 220 | return false; 221 | } 222 | if (getClass() != obj.getClass()) { 223 | return false; 224 | } 225 | CombinatoricsVector other = (CombinatoricsVector) obj; 226 | if (_vector == null) { 227 | if (other._vector != null) { 228 | return false; 229 | } 230 | } else if (!_vector.equals(other._vector)) { 231 | return false; 232 | } 233 | return true; 234 | } 235 | 236 | /** 237 | * Clear the elements. 238 | */ 239 | @Override 240 | public void clearVector() { 241 | _vector.clear(); 242 | } 243 | 244 | /** 245 | * Returns an iterator over the current vector. 246 | * 247 | * @return an Iterator. 248 | */ 249 | @Override 250 | public Iterator iterator() { 251 | return _vector.iterator(); 252 | } 253 | 254 | /** 255 | * Returns vector as a string. 256 | * 257 | * @see java.lang.Object#toString() 258 | */ 259 | @Override 260 | public String toString() { 261 | return "CombinatoricsVector=(" + _vector + ", size=" + getSize() + ")"; 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /src/test/java/org/paukov/combinatorics/partition/PartitionsTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Combinatorics Library 3 | * Copyright 2012 Dmytro Paukov d.paukov@gmail.com 4 | */ 5 | package org.paukov.combinatorics.partition; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.paukov.combinatorics.CombinatoricsFactory.createPartitionGenerator; 9 | 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import org.junit.Test; 13 | import org.paukov.combinatorics.Generator; 14 | import org.paukov.combinatorics.ICombinatoricsVector; 15 | import org.paukov.combinatorics.IFilter; 16 | 17 | /** 18 | * @author Dmytro Paukov 19 | */ 20 | public final class PartitionsTest { 21 | 22 | @Test 23 | public void simplePartition() { 24 | 25 | Generator partitionGenerator = createPartitionGenerator(5); 26 | Iterator> partitionIterator = partitionGenerator.iterator(); 27 | 28 | System.out.println("Number of partition is: " 29 | + partitionGenerator.getNumberOfGeneratedObjects()); 30 | assertEquals(8, partitionGenerator.getNumberOfGeneratedObjects()); 31 | 32 | while (partitionIterator.hasNext()) { 33 | partitionIterator.next(); 34 | System.out.println(partitionIterator); 35 | } 36 | 37 | List> list = partitionGenerator.generateAllObjects(); 38 | 39 | assertEquals(5, partitionGenerator.getOriginalVector().getValue(0).intValue()); 40 | 41 | assertEquals(7, list.size()); 42 | 43 | assertEquals("CombinatoricsVector=([1, 1, 1, 1, 1], size=5)", 44 | list.get(0).toString()); 45 | assertEquals("CombinatoricsVector=([2, 1, 1, 1], size=4)", list.get(1) 46 | .toString()); 47 | assertEquals("CombinatoricsVector=([2, 2, 1], size=3)", list.get(2) 48 | .toString()); 49 | assertEquals("CombinatoricsVector=([3, 1, 1], size=3)", list.get(3) 50 | .toString()); 51 | assertEquals("CombinatoricsVector=([3, 2], size=2)", list.get(4) 52 | .toString()); 53 | assertEquals("CombinatoricsVector=([4, 1], size=2)", list.get(5) 54 | .toString()); 55 | assertEquals("CombinatoricsVector=([5], size=1)", list.get(6) 56 | .toString()); 57 | } 58 | 59 | @Test 60 | public void simpleTwoPartition() { 61 | 62 | Generator partitionGenerator = createPartitionGenerator(2); 63 | Iterator> partitionIterator = partitionGenerator.iterator(); 64 | 65 | System.out.println("Number of partition is: " 66 | + partitionGenerator.getNumberOfGeneratedObjects()); 67 | assertEquals(2, partitionGenerator.getNumberOfGeneratedObjects()); 68 | 69 | while (partitionIterator.hasNext()) { 70 | partitionIterator.next(); 71 | System.out.println(partitionIterator); 72 | } 73 | 74 | List> list = partitionGenerator.generateAllObjects(); 75 | 76 | assertEquals(2, list.size()); 77 | 78 | assertEquals("CombinatoricsVector=([1, 1], size=2)", list.get(0) 79 | .toString()); 80 | assertEquals("CombinatoricsVector=([2], size=1)", list.get(1) 81 | .toString()); 82 | } 83 | 84 | @Test 85 | public void simpleOnePartition() { 86 | 87 | Generator partitionGenerator = createPartitionGenerator(1); 88 | Iterator> partitionIterator = partitionGenerator.iterator(); 89 | 90 | System.out.println("Number of partition is: " 91 | + partitionGenerator.getNumberOfGeneratedObjects()); 92 | assertEquals(1, partitionGenerator.getNumberOfGeneratedObjects()); 93 | 94 | while (partitionIterator.hasNext()) { 95 | partitionIterator.next(); 96 | System.out.println(partitionIterator); 97 | } 98 | 99 | List> list = partitionGenerator.generateAllObjects(); 100 | 101 | assertEquals(1, list.size()); 102 | 103 | assertEquals("CombinatoricsVector=([1], size=1)", list.get(0) 104 | .toString()); 105 | } 106 | 107 | @Test 108 | public void simpleEmptyPartition() { 109 | 110 | Generator partitionGenerator = createPartitionGenerator(0); 111 | Iterator> partitionIterator = partitionGenerator.iterator(); 112 | 113 | System.out.println("Number of partition is: " 114 | + partitionGenerator.getNumberOfGeneratedObjects()); 115 | assertEquals(0, partitionGenerator.getNumberOfGeneratedObjects()); 116 | 117 | while (partitionIterator.hasNext()) { 118 | partitionIterator.next(); 119 | System.out.println(partitionIterator); 120 | } 121 | 122 | List> list = partitionGenerator.generateAllObjects(); 123 | 124 | assertEquals(0, list.size()); 125 | } 126 | 127 | @Test 128 | public void mostThreeIntegersPartition() { 129 | 130 | Generator partitionGenerator = createPartitionGenerator(8); 131 | 132 | List> list = partitionGenerator 133 | .generateFilteredObjects(new IFilter>() { 134 | 135 | @Override 136 | public boolean accepted(long index, 137 | ICombinatoricsVector value) { 138 | return value.getSize() <= 3; 139 | } 140 | }); 141 | 142 | assertEquals(10, list.size()); 143 | 144 | assertEquals("CombinatoricsVector=([3, 3, 2], size=3)", list.get(0) 145 | .toString()); 146 | assertEquals("CombinatoricsVector=([4, 2, 2], size=3)", list.get(1) 147 | .toString()); 148 | assertEquals("CombinatoricsVector=([4, 3, 1], size=3)", list.get(2) 149 | .toString()); 150 | assertEquals("CombinatoricsVector=([4, 4], size=2)", list.get(3) 151 | .toString()); 152 | assertEquals("CombinatoricsVector=([5, 2, 1], size=3)", list.get(4) 153 | .toString()); 154 | assertEquals("CombinatoricsVector=([5, 3], size=2)", list.get(5) 155 | .toString()); 156 | assertEquals("CombinatoricsVector=([6, 1, 1], size=3)", list.get(6) 157 | .toString()); 158 | assertEquals("CombinatoricsVector=([6, 2], size=2)", list.get(7) 159 | .toString()); 160 | assertEquals("CombinatoricsVector=([7, 1], size=2)", list.get(8) 161 | .toString()); 162 | assertEquals("CombinatoricsVector=([8], size=1)", list.get(9) 163 | .toString()); 164 | } 165 | 166 | @Test 167 | public void exactlyThreeIntegersPartition() { 168 | 169 | Generator partitionGenerator = createPartitionGenerator(8); 170 | 171 | List> list = partitionGenerator 172 | .generateFilteredObjects(new IFilter>() { 173 | 174 | @Override 175 | public boolean accepted(long index, 176 | ICombinatoricsVector value) { 177 | return value.getSize() == 3; 178 | } 179 | }); 180 | 181 | assertEquals(5, list.size()); 182 | 183 | assertEquals("CombinatoricsVector=([3, 3, 2], size=3)", list.get(0) 184 | .toString()); 185 | assertEquals("CombinatoricsVector=([4, 2, 2], size=3)", list.get(1) 186 | .toString()); 187 | assertEquals("CombinatoricsVector=([4, 3, 1], size=3)", list.get(2) 188 | .toString()); 189 | assertEquals("CombinatoricsVector=([5, 2, 1], size=3)", list.get(3) 190 | .toString()); 191 | assertEquals("CombinatoricsVector=([6, 1, 1], size=3)", list.get(4) 192 | .toString()); 193 | } 194 | 195 | @Test(expected = RuntimeException.class) 196 | public void getNumberOfGeneratedObjects_initialValue_too_big() { 197 | Generator partitionGenerator = createPartitionGenerator(101); 198 | partitionGenerator.getNumberOfGeneratedObjects(); 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | --------------------------------------------------------------------------------