import javax.imageio.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.*;
import java.security.NoSuchAlgorithmException;
import java.security.MessageDigest;
import java.lang.reflect.*;
import java.net.*;
import java.io.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.*;
import java.util.concurrent.*;
import java.util.regex.*;
import java.util.List;
import java.util.zip.*;
import java.util.*;
public class main {
static String sentence1 = "Yes is the opposite of no. No is the opposite of yes.";
static String sentence2 = "Green is the opposite of white.";
// Now uses TreeMap for nicer sorting (i.e., A must be a orderable type)
static class MultiSet {
Map map = new TreeMap();
public MultiSet() {
}
public MultiSet(A key) {
add(key);
}
public void add(A key) {
add(key, 1);
}
public void add(A key, int count) {
if (map.containsKey(key))
map.put(key, map.get(key)+count);
else
map.put(key, count);
}
public int get(A key) {
return map.containsKey(key) ? map.get(key) : 0;
}
public void remove(A key) {
Integer i = map.get(key);
if (i != null && i > 1)
map.put(key, i - 1);
else
map.remove(key);
}
public List getTopTen(int maxSize) {
List list = getSortedListDescending();
return list.size() > maxSize ? list.subList(0, maxSize) : list;
}
public List getSortedListDescending() {
List list = new ArrayList(map.keySet());
Collections.sort(list, new Comparator() {
public int compare(A a, A b) {
return map.get(b).compareTo(map.get(a));
}
});
return list;
}
public int getNumberOfUniqueElements() {
return map.size();
}
public Set asSet() {
return map.keySet();
}
public A getMostPopularEntry() {
int max = 0;
A a = null;
for (Map.Entry entry : map.entrySet()) {
if (entry.getValue() > max) {
max = entry.getValue();
a = entry.getKey();
}
}
return a;
}
public void removeAll(A key) {
map.remove(key);
}
/*public A getRandomEntry(Randomizer rand) {
int total = size(), n = rand.getRandomNumber(total);
for (Map.Entry entry : map.entrySet()) {
n -= entry.getValue();
if (n < 0)
return entry.getKey();
}
throw new RuntimeException("huch");
}*/
public int size() {
int size = 0;
for (int i : map.values())
size += i;
return size;
}
public MultiSet mergeWith(MultiSet set) {
MultiSet result = new MultiSet();
for (A a : set.asSet()) {
result.add(a, set.get(a));
}
return result;
}
public boolean isEmpty() {
return map.isEmpty();
}
} // MultiSet
public static void main(String[] args) throws Exception {
List tok1 = parse(sentence1);
List tok2 = parse(sentence2);
Map> map = makeMMapPrefix(tok1, tok2);
if (map == null)
print("No match.");
else
print(structure(map));
print(complete(sentence1, sentence2));
}
static List parse(String s) {
return tokensToLowerCase(javaTok(s));
}
static String complete(String sentence1, String sentence2) {
List tok1 = parse(sentence1);
List tok2 = parse(sentence2);
Map> map = makeMMapPrefix(tok1, tok2);
if (map == null) return null;
List tok = new ArrayList();
tok.addAll(tok2.subList(0, tok2.size()-1));
for (int i = tok2.size()-1; i < tok1.size(); i++) {
String t = tok1.get(i);
MultiSet set = map.get(t);
tok.add(set == null ? t : set.getMostPopularEntry());
}
return join(tok);
}
static Map> makeMMapPrefix(List tok1, List tok2) {
if (tok1.size() < tok2.size()) return null;
Map> map = new TreeMap>();
for (int i = 1; i < tok2.size(); i += 2) {
String t1 = tok1.get(i), t2 = tok2.get(i);
MultiSet set = map.get(t1);
if (set == null)
map.put(t1, new MultiSet(t2));
else
set.add(t2);
}
// match succeeds
return map;
}
static List tokensToLowerCase(List tok) {
tok = new ArrayList(tok);
for (int i = 1; i < tok.size(); i += 2)
tok.set(i, tok.get(i).toLowerCase());
return tok;
}
// replacement for class JavaTok
// maybe incomplete, might want to add floating point numbers
// todo also: extended multi-line strings
static List javaTok(String s) {
List tok = new ArrayList();
int l = s.length();
int i = 0;
while (i < l) {
int j = i;
char c; String cc;
// scan for whitespace
while (j < l) {
c = s.charAt(j);
cc = s.substring(j, Math.min(j+2, l));
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
++j;
else if (cc.equals("/*")) {
do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/"));
j = Math.min(j+2, l);
} else if (cc.equals("//")) {
do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0);
} else
break;
}
tok.add(s.substring(i, j));
i = j;
if (i >= l) break;
c = s.charAt(i); // cc is not needed in rest of loop body
cc = s.substring(i, Math.min(i+2, l));
// scan for non-whitespace
if (c == '\'' || c == '"') {
char opener = c;
++j;
while (j < l) {
if (s.charAt(j) == opener) {
++j;
break;
} else if (s.charAt(j) == '\\' && j+1 < l)
j += 2;
else
++j;
}
} else if (Character.isJavaIdentifierStart(c))
do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j)));
else if (Character.isDigit(c))
do ++j; while (j < l && Character.isDigit(s.charAt(j)));
else if (cc.equals("[[")) {
do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]"));
j = Math.min(j+2, l);
} else
++j;
tok.add(s.substring(i, j));
i = j;
}
if ((tok.size() % 2) == 0) tok.add("");
return tok;
}
static void print() {
System.out.println();
}
static void print(Object o) {
System.out.println(o);
}
static void print(long i) {
System.out.println(i);
}
static void set(Class c, String field, Object value) {
try {
Field f = set_findStaticField(c, field);
f.setAccessible(true);
f.set(null, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field set_findStaticField(Class> c, String field) {
for (Field f : c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0)
return f;
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
public static String join(String glue, Iterable strings) {
StringBuilder buf = new StringBuilder();
Iterator i = strings.iterator();
if (i.hasNext()) {
buf.append(i.next());
while (i.hasNext())
buf.append(glue).append(i.next());
}
return buf.toString();
}
public static String join(String glue, String[] strings) {
return join(glue, Arrays.asList(strings));
}
public static String join(Iterable strings) {
return join("", strings);
}
public static String join(String[] strings) {
return join("", strings);
}
static Object get(Object o, String field) {
if (o instanceof Class) return get((Class) o, field);
try {
Field f = get_findField(o.getClass(), field);
f.setAccessible(true);
return f.get(o);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
f.setAccessible(true);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
for (Field f : c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & Modifier.STATIC) != 0)
return f;
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
for (Field f : c.getDeclaredFields())
if (f.getName().equals(field))
return f;
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static String structure(Object o) {
return structure(o, 0);
}
static String structure(Object o, int stringSizeLimit) {
if (o == null) return "null";
String name = o.getClass().getName();
StringBuilder buf = new StringBuilder();
if (o instanceof Collection) {
for (Object x : (Collection) o) {
if (buf.length() != 0) buf.append(", ");
buf.append(structure(x, stringSizeLimit));
}
return "{" + buf + "}";
}
if (o instanceof Map) {
for (Object e : ((Map) o).entrySet()) {
if (buf.length() != 0) buf.append(", ");
buf.append(structure(((Map.Entry) e).getKey(), stringSizeLimit));
buf.append("=");
buf.append(structure(((Map.Entry) e).getValue(), stringSizeLimit));
}
return "{" + buf + "}";
}
if (o.getClass().isArray()) {
int n = Array.getLength(o);
for (int i = 0; i < n; i++) {
if (buf.length() != 0) buf.append(", ");
buf.append(structure(Array.get(o, i), stringSizeLimit));
}
return "{" + buf + "}";
}
if (o instanceof String)
return quote(stringSizeLimit != 0 ? shorten((String) o, stringSizeLimit) : (String) o);
// Need more cases? This should cover all library classes...
if (name.startsWith("java.") || name.startsWith("javax."))
return String.valueOf(o);
String shortName = o.getClass().getName().replaceAll("^main\\$", "");
// TODO: go to superclasses too
Field[] fields = o.getClass().getDeclaredFields();
int numFields = 0;
String fieldName = "";
for (Field field : fields) {
if ((field.getModifiers() & Modifier.STATIC) != 0)
continue;
Object value;
try {
value = field.get(o);
} catch (Exception e) {
value = "?";
}
fieldName = field.getName();
// put special cases here...
if (value != null) {
if (buf.length() != 0) buf.append(", ");
buf.append(fieldName + "=" + structure(value, stringSizeLimit));
}
++numFields;
}
String b = buf.toString();
if (numFields == 1)
b = b.replaceAll("^" + fieldName + "=", ""); // drop field name if only one
String s = shortName;
if (buf.length() != 0)
s += "(" + b + ")";
return s;
}
public static String quote(String s) {
if (s == null) return "null";
return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\r", "\\r").replace("\n", "\\n") + "\"";
}
static String shorten(String s, int max) {
return s.length() <= max ? s : s.substring(0, Math.min(s.length(), max)) + "...";
}
}