| /workspace/code/ProgPraxis/src/progpraxis/WordCubeSolver.java |
1 /** 2 * Author: Elvis Montero 3 * URL: www.elvismontero.com 4 * License: This code is licensed under the Creative Commons Attribution 5 * Share-Alike License v3.0 or any other later version. 6 */ 7 8 package progpraxis; 9 10 import java.io.BufferedReader; 11 import java.io.FileReader; 12 import java.io.IOException; 13 import java.util.Set; 14 import java.util.TreeSet; 15 import java.math.BigInteger; 16 import java.util.ArrayList; 17 import java.util.List; 18 19 public class WordCubeSolver { 20 21 private enum FILE { 22 23 CONNECTIVES("connectives"), PROPERNAMES("propernames"), WORDS("web2"), WORDS2("web2a"); 24 25 FILE(String value) { 26 fileName = value; 27 } 28 private String fileName; 29 30 @Override 31 public String toString() { 32 return this.fileName; 33 } 34 } 35 36 public static void main(String[] args) { 37 long startTime = System.nanoTime(); 38 if (args == null || args.length < 2 || args[0].length() != 9) { 39 throw new IllegalArgumentException("Usage: java WordCubeSolver CUBE_AS_9_CHAR_STRING PATH_TO_DICT_ROOT"); 40 } 41 42 // Load dictionary to memory 43 Set<String> dictionary = loadDictionary(args[1]); 44 45 // Generate all unique, sorted permutations for each case 46 Set<String> fourLetterWords = generateWords(toStringArray(args[0]), 4, args[0].charAt(4) + ""); 47 Set<String> fiveLetterWords = generateWords(toStringArray(args[0]), 5, args[0].charAt(4) + ""); 48 Set<String> sixLetterWords = generateWords(toStringArray(args[0]), 6, args[0].charAt(4) + ""); 49 Set<String> sevenLetterWords = generateWords(toStringArray(args[0]), 7, args[0].charAt(4) + ""); 50 Set<String> eightLetterWords = generateWords(toStringArray(args[0]), 8, args[0].charAt(4) + ""); 51 Set<String> nineLetterWords = generateWords(toStringArray(args[0]), 9, args[0].charAt(4) + ""); 52 53 System.out.println("Words found in the dictionary for the given Word Cube: "); 54 // Check if any of the generated words is part of the dictionary 55 check(fourLetterWords, dictionary); 56 check(fiveLetterWords, dictionary); 57 check(sixLetterWords, dictionary); 58 check(sevenLetterWords, dictionary); 59 check(eightLetterWords, dictionary); 60 check(nineLetterWords, dictionary); 61 62 long endTime = System.nanoTime(); 63 System.out.println("Done! Elapsed time: " + (endTime - startTime) / (double) (1000000000) + " secs"); 64 } 65 66 private static Set<String> loadDictionary(String pathToDict) { 67 pathToDict = (pathToDict.endsWith("/")) ? pathToDict : pathToDict + "/"; 68 Set<String> dict = new TreeSet<String>(); 69 for (FILE fileName : FILE.values()) { 70 try { 71 BufferedReader input = new BufferedReader(new FileReader(pathToDict + fileName.toString())); 72 String line = null; 73 while ((line = input.readLine()) != null) { 74 dict.add(line.trim()); 75 } 76 input.close(); 77 } catch (IOException exception) { 78 System.out.println("The dictionary couldn't be read!"); 79 System.exit(1); 80 } 81 } 82 83 return dict; 84 } 85 86 private static void check(Set<String> words, Set<String> dict) { 87 for (String word : words) { 88 if (dict.contains(word)) { 89 System.out.println(word); 90 } 91 } 92 } 93 94 private static Set<String> generateWords(String[] elements, int k, String mandatory) { 95 List<String> combinations = new ArrayList<String>(); 96 int[] indices; 97 CombinationGenerator x = new CombinationGenerator(elements.length, k); 98 StringBuffer combination; 99 while (x.hasMore()) { 100 combination = new StringBuffer(); 101 indices = x.getNext(); 102 for (int i = 0; i < indices.length; i++) { 103 combination.append(elements[indices[i]]); 104 } 105 if (combination.indexOf(mandatory) == -1) { 106 continue; 107 } 108 combinations.add(combination.toString()); 109 } 110 111 Set<String> permutations = new TreeSet<String>(); 112 113 // Unique, sorted permutations for each combination 114 for (String comb : combinations) { 115 int[] pos; 116 String[] combElements = toStringArray(comb); 117 PermutationGenerator permEngine = new PermutationGenerator(combElements.length); 118 StringBuffer permutation; 119 while (permEngine.hasMore()) { 120 permutation = new StringBuffer(); 121 pos = permEngine.getNext(); 122 for (int i = 0; i < pos.length; i++) { 123 permutation.append(combElements[pos[i]]); 124 } 125 permutations.add(permutation.toString()); 126 } 127 } 128 129 return permutations; 130 } 131 132 private static String[] toStringArray(String input) { 133 String[] result = new String[input.length()]; 134 for (int i = 0; i < result.length; i++) { 135 result[i] = input.charAt(i) + ""; 136 } 137 return result; 138 } 139 } 140 141 // Permutation Generator by Michael Gilleland. 142 // Read more at http://www.merriampark.com/perm.htm 143 class PermutationGenerator { 144 145 private int[] a; 146 private BigInteger numLeft; 147 private BigInteger total; 148 149 public PermutationGenerator(int n) { 150 if (n < 1) { 151 throw new IllegalArgumentException("Min 1"); 152 } 153 a = new int[n]; 154 total = getFactorial(n); 155 reset(); 156 } 157 158 public final void reset() { 159 for (int i = 0; i < a.length; i++) { 160 a[i] = i; 161 } 162 numLeft = new BigInteger(total.toString()); 163 } 164 165 public BigInteger getNumLeft() { 166 return numLeft; 167 } 168 169 public BigInteger getTotal() { 170 return total; 171 } 172 173 public boolean hasMore() { 174 return numLeft.compareTo(BigInteger.ZERO) == 1; 175 } 176 177 private static BigInteger getFactorial(int n) { 178 BigInteger fact = BigInteger.ONE; 179 for (int i = n; i > 1; i--) { 180 fact = fact.multiply(new BigInteger(Integer.toString(i))); 181 } 182 return fact; 183 } 184 185 public int[] getNext() { 186 187 if (numLeft.equals(total)) { 188 numLeft = numLeft.subtract(BigInteger.ONE); 189 return a; 190 } 191 192 int temp; 193 int j = a.length - 2; 194 while (a[j] > a[j + 1]) { 195 j--; 196 } 197 198 int k = a.length - 1; 199 while (a[j] > a[k]) { 200 k--; 201 } 202 203 temp = a[k]; 204 a[k] = a[j]; 205 a[j] = temp; 206 207 int r = a.length - 1; 208 int s = j + 1; 209 210 while (r > s) { 211 temp = a[s]; 212 a[s] = a[r]; 213 a[r] = temp; 214 r--; 215 s++; 216 } 217 218 numLeft = numLeft.subtract(BigInteger.ONE); 219 return a; 220 } 221 } 222 223 // Combinations Generator by Michael Gilleland. 224 // Read more at http://www.merriampark.com/comb.htm 225 class CombinationGenerator { 226 227 private int[] a; 228 private int n; 229 private int r; 230 private BigInteger numLeft; 231 private BigInteger total; 232 233 public CombinationGenerator(int n, int r) { 234 if (r > n) { 235 throw new IllegalArgumentException(); 236 } 237 if (n < 1) { 238 throw new IllegalArgumentException(); 239 } 240 this.n = n; 241 this.r = r; 242 a = new int[r]; 243 BigInteger nFact = getFactorial(n); 244 BigInteger rFact = getFactorial(r); 245 BigInteger nminusrFact = getFactorial(n - r); 246 total = nFact.divide(rFact.multiply(nminusrFact)); 247 reset(); 248 } 249 250 public final void reset() { 251 for (int i = 0; i < a.length; i++) { 252 a[i] = i; 253 } 254 numLeft = new BigInteger(total.toString()); 255 } 256 257 public BigInteger getNumLeft() { 258 return numLeft; 259 } 260 261 public boolean hasMore() { 262 return numLeft.compareTo(BigInteger.ZERO) == 1; 263 } 264 265 public BigInteger getTotal() { 266 return total; 267 } 268 269 private static BigInteger getFactorial(int n) { 270 BigInteger fact = BigInteger.ONE; 271 for (int i = n; i > 1; i--) { 272 fact = fact.multiply(new BigInteger(Integer.toString(i))); 273 } 274 return fact; 275 } 276 277 public int[] getNext() { 278 279 if (numLeft.equals(total)) { 280 numLeft = numLeft.subtract(BigInteger.ONE); 281 return a; 282 } 283 284 int i = r - 1; 285 while (a[i] == n - r + i) { 286 i--; 287 } 288 a[i] = a[i] + 1; 289 for (int j = i + 1; j < r; j++) { 290 a[j] = a[i] + j - i; 291 } 292 293 numLeft = numLeft.subtract(BigInteger.ONE); 294 return a; 295 296 } 297 }