2010年1月19日 星期二

combination enumerator in java

  1.  
  2. /*
  3. Combination.java
  4.  
  5. generates all combinations of C(n,m) for n >= m >= 0
  6.  
  7. Usage: java Combination n m
  8.  
  9. Sample Output:
  10. > java Combination 5 2
  11. --- recursive one-shot generation ---
  12. k=1 ---> {1, 2}
  13. k=2 ---> {1, 3}
  14. k=3 ---> {1, 4}
  15. k=4 ---> {1, 5}
  16. k=5 ---> {2, 3}
  17. k=6 ---> {2, 4}
  18. k=7 ---> {2, 5}
  19. k=8 ---> {3, 4}
  20. k=9 ---> {3, 5}
  21. k=10 ---> {4, 5}
  22. --- nonrecursive item-wise generation ---
  23. k=1 ---> {1, 2}
  24. k=2 ---> {1, 3}
  25. k=3 ---> {1, 4}
  26. k=4 ---> {1, 5}
  27. k=5 ---> {2, 3}
  28. k=6 ---> {2, 4}
  29. k=7 ---> {2, 5}
  30. k=8 ---> {3, 4}
  31. k=9 ---> {3, 5}
  32. k=10 ---> {4, 5}
  33.  
  34. --- Combination.java ---
  35. */
  36. import java.util.Vector;
  37. import java.util.Enumeration;
  38.  
  39. // class for generating all m-item selection sets from an n-item population set
  40. public class Combination {
  41. Vector < Object > n_set; // population set of objects for combination
  42. int n; // population size, n >= m >= 0
  43. int m; // selection size
  44.  
  45. // constructor for combination object
  46. // n_set: population set of objects for combination
  47. // m: selection size
  48. public Combination(Vector < Object > n_set, int m) {
  49. this.n_set = n_set;
  50. this.n = n_set.size();
  51. this.m = m;
  52.  
  53. if (n < m || m < 0 || n <= 0) {
  54. System.err.printf("combine(n=%d, m=%d): illegal n,m!\n", n, m);
  55. }
  56. }
  57.  
  58. // generate integer objects from 1 to n
  59. public static Vector < Object > generateIntegers(int n) {
  60. Vector < Object > set = new Vector < Object > ();
  61. for (int i = 1; i <= n; i++) set.add(i);
  62. return set;
  63. }
  64.  
  65. // generate integer objects from 1 to n
  66. public static Vector < Vector < Object >> cnm(int n, int m) {
  67. Vector < Object > set = generateIntegers(n);
  68. Combination c = new Combination(set, m);
  69. Vector < Vector < Object >> set_list = c.cnm();
  70. return set_list;
  71. }
  72.  
  73. // generate all m-item selection sets from population set n_set
  74. // returns set of all m-item selection sets from population set n_set
  75. Vector < Vector < Object >> cnm() {
  76. return cnm(n_set, m);
  77. }
  78.  
  79. // recursive generation of all m-item selection sets from population set n_set
  80. // n_set: population set
  81. // m: selection size
  82. // returns set of all m-item selection sets from population set n_set
  83. Vector < Vector < Object >> cnm(Vector < Object > n_set, int m) {
  84. Vector < Object > set = new Vector < Object > ();
  85. Vector < Vector < Object >> result_list = new Vector < Vector < Object >> ();
  86.  
  87. int n = n_set.size();
  88. if (n < m || m < 0 || n <= 0) {
  89. System.err.printf("combine(n=%d, m=%d): illegal n,m!\n", n, m);
  90. return null;
  91. }
  92.  
  93. // base case 1: m=0
  94. if (m == 0) {
  95. result_list.add(set);
  96. return result_list;
  97. }
  98. // base case 2: m=n
  99. else if (m == n) {
  100. result_list.add(n_set);
  101. return result_list;
  102. }
  103.  
  104. // recursive call:
  105. Vector < Vector < Object >> result_with_first = new Vector < Vector < Object >> ();
  106. Vector < Vector < Object >> result_without_first = new Vector < Vector < Object >> ();
  107.  
  108. Vector < Object > n_minus_1_set = new Vector < Object > (n_set);
  109. n_minus_1_set.removeElementAt(0);
  110. result_with_first = cnm(n_minus_1_set, m - 1);
  111. result_without_first = cnm(n_minus_1_set, m);
  112. for (Vector < Object > comb: result_with_first) {
  113. comb.insertElementAt(n_set.firstElement(), 0);
  114. }
  115.  
  116. result_list.addAll(result_with_first);
  117. result_list.addAll(result_without_first);
  118.  
  119. return result_list;
  120. }
  121.  
  122. // get enumerator for all m-item selection sets from population set n_set
  123. Enumeration < Vector < Object >> enumeration() {
  124. if (n < m || m < 0 || n <= 0) {
  125. System.err.printf("combine(n=%d, m=%d): illegal n,m!\n", n, m);
  126. return null;
  127. }
  128. return new Enumerator();
  129. }
  130.  
  131. // inner class of Combination class
  132. // enumerator for non-recursive generation of all m-item selection sets from population set n_set
  133. public class Enumerator implements Enumeration < Vector < Object >> {
  134. int index[];
  135. int index_upper[];
  136. boolean carry;
  137. boolean hasMore;
  138. Vector < Object > element;
  139.  
  140. // constructor for m-item selection set enumerator
  141. public Enumerator() {
  142. element = new Vector < Object > ();
  143. hasMore = true;
  144.  
  145. //carry = new boolean[m];
  146. index = new int[m];
  147. index_upper = new int[m];
  148. for (int i = 0; i <= m - 1; i++) {
  149. index[i] = i;
  150. index_upper[i] = n - m + i;
  151. }
  152. }
  153.  
  154. public boolean hasMoreElements() {
  155. return hasMore;
  156. }
  157.  
  158. public Vector < Object > nextElement() {
  159. int i;
  160. element.clear();
  161. for (i = 0; i <= m - 1; i++) {
  162. element.add(n_set.get(index[i]));
  163. }
  164.  
  165. // point to next index
  166. carry = false;
  167. for (i = m - 1; i >= 0; i--) {
  168. int digit = index[i];
  169. if (digit + 1 <= index_upper[i]) {
  170. index[i]++;
  171.  
  172. if (carry == true)
  173. while (i + 1 <= m - 1) {
  174. index[i + 1] = index[i] + 1;
  175. i++;
  176. }
  177. break;
  178. } else
  179. carry = true;
  180. }
  181.  
  182. if (i < 0) hasMore = false;
  183. return element;
  184. } // end of nextElement
  185. } // end of enumerator class
  186.  
  187. // main program for test
  188. public static void main(String args[]) {
  189. int n = 5;
  190. int m = 2;
  191.  
  192. if (args.length == 2) {
  193. n = Integer.parseInt(args[0]);
  194. m = Integer.parseInt(args[1]);
  195. }
  196.  
  197. System.out.println("--- recursive one-shot generation ---");
  198.  
  199. Vector < Vector < Object >> set_list = Combination.cnm(n, m);
  200. int k = 1;
  201. for (Vector < Object > set: set_list) {
  202. System.out.printf("k=%d ---> {", k);
  203. boolean first = true;
  204. for (Object o: set) {
  205. if (first) first = false;
  206. else System.out.print(", ");
  207. System.out.print((Integer) o);
  208. }
  209. System.out.println("}");
  210. k++;
  211. }
  212.  
  213. System.out.println("--- nonrecursive item-wise generation ---");
  214.  
  215. Vector < Object > set = Combination.generateIntegers(n);
  216. Combination c = new Combination(set, m);
  217. Enumeration < Vector < Object >> e = c.enumeration();
  218. k = 1;
  219. while (e.hasMoreElements()) {
  220. set = e.nextElement();
  221. System.out.printf("k=%d ---> {", k);
  222. boolean first = true;
  223. for (Object o: set) {
  224. if (first) first = false;
  225. else System.out.print(", ");
  226. System.out.print((Integer) o);
  227. }
  228. System.out.println("}");
  229. k++;
  230. }
  231. }
  232. }
註: 本程式使用 GitHub JavaScript code prettifier 工具標示顏色。其方法如下: 1.參考 [Blogger] 如何在 Blogger 顯示程式碼 - Google Code Prettify 於【Blogger 版面配置 HTML/JavaScript小工具】安裝如下套件 <script src="https://cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js"></script> 2.文章編輯再以HTML模式為程式包上如下標籤。 <code class="prettyprint lang-java linenums"> ... </code>

沒有留言: