import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Scanner; public class Phase3 { public static final String regex = "[a-z]+"; public static char alphabet[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', }; public static BitSet[] seen_nform = { new BitSet(), new BitSet(26), new BitSet(325), new BitSet(2600), new BitSet(14950), new BitSet(65780), new BitSet(230230), new BitSet(657800), new BitSet(1562275), new BitSet(3124550), new BitSet(5311735), new BitSet(7726160), new BitSet(9657700), new BitSet(10400600), new BitSet(9657700), new BitSet(7726160), new BitSet(5311735), new BitSet(3124550), new BitSet(1562275), new BitSet(657800), new BitSet(230230), new BitSet(65780), new BitSet(14950), new BitSet(2600), new BitSet(325), new BitSet(26), new BitSet(1) }; public static HashMap lookup = new HashMap(26); public static void main(String[] args) { initlookup(); Scanner scr1, scr2; String line; LinkedHashMap word = new LinkedHashMap(3477); // Load phase1.data into word try { scr1 = new Scanner(new File(args[0])); while (scr1.hasNextLine()) { line = scr1.nextLine(); scr2 = new Scanner(line); word.put(scr2.next(regex), scr2.next(regex)); } } catch (IOException ioe) { ioe.printStackTrace(); } // Process phase2.data String nform, str1, str2; try { scr1 = new Scanner(new File(args[1])); while (scr1.hasNextLine()) { line = scr1.nextLine(); scr2 = new Scanner(line); nform = scr2.next(regex); str1 = scr2.next(regex); str2 = scr2.next(regex); HashSet seen = new HashSet(); ArrayList new_word = new ArrayList(); for (Map.Entry entry : word.entrySet()) { String new_nform = uniq(nform, entry.getValue()); int len = new_nform.length(); int bit = getBit(len, new_nform); if (seen_nform[len].get(bit)) { continue; } String new_let = diff(entry.getKey(), nform); if (new_let.length() == 0 || seen.contains(new_let)) { continue; } seen.add(new_let); String[] e = {entry.getValue(), new_let, new_nform, Integer.toString(bit)}; new_word.add(e); } String[] new1, new2; int idx; int end = new_word.size(); for (int i = 0; i < end - 1; ++i) { new1 = new_word.get(i); if (new1 == null) { continue; } for (int j = i + 1; j < end; ++j) { new2 = new_word.get(j); if (new2 == null) { continue; } idx = j; if (new2[1].length() > new1[1].length()) { String[] temp = new1; new1 = new2; new2 = temp; idx = i; } int res = distinct(new1[1], new2[1]); if (res == 0) { new_word.set(idx, null); } } } for (String[] e : new_word) { if (e == null) { continue; } String str3 = e[0]; String new_nform = e[2]; int len = new_nform.length(); int bit = Integer.decode(e[3]); /* Probably not needed */ if (seen_nform[len].get(bit)) { continue; } seen_nform[len].set(bit); System.out.println(new_nform + "\t" + str1 + "\t" + str2 + "\t" + str3); } } } catch (IOException ioe) { ioe.printStackTrace(); } } private static void initlookup () { // Actual code goes a-z, reduced for post lookup.put('a', new Integer("1")); lookup.put('b', new Integer("2")); } // Determine Chars in str1 not present in str2 private static String diff(String str1, String str2) { int len = str2.length(); HashSet have = new HashSet(len); for (Character c : str2.toCharArray()) { have.add(c); } StringBuilder new_let = new StringBuilder(len); for (Character c : str1.toCharArray()) { if (have.contains(c)) { continue; } new_let.append(c); } return new_let.toString(); } // Determine if str2 (shorter) contains any chars not in str1 (longer) private static int distinct(String str1, String str2) { HashSet have = new HashSet(str1.length()); for (Character c : str1.toCharArray()) { have.add(c); } for (Character c : str2.toCharArray()) { if (have.contains(c)) { continue; } return 1; } return 0; } // List of unique chars in alphabetic order in str1 & str2 private static String uniq(String str1, String str2) { HashSet have = new HashSet(); for (Character c : str1.toCharArray()) { have.add(c); } for (Character c : str2.toCharArray()) { have.add(c); } StringBuilder unique = new StringBuilder(26); for (char let : alphabet) { if (have.contains(let)) { unique.append(let); } } return unique.toString(); } private static int binomial(int n, int k) { int c = 1; for (int i = 0; i < k; ++i) { c *= n - i; c /= i + 1; } return c; } private static int getBit(int len, String str) { int sum = 0; for (int i = 0; i < len; ++i) { sum += binomial(lookup.get(str.charAt(i)) - 1, i + 1); } return sum; } }