import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
class main {
static class DeepWordIndex {
boolean _isTransient() { return true; }
String regexp = "\\w+";
boolean useHashMaps = false; // makes it case-sensitive and doesn't allow partial word searches
boolean sortEntries = false; // if A implements Comparable
Map> entries = new HashMap();
//new L> entriesList;
MultiSetMap> entriesByWord;
Map>> entriesByWord_lists;
static class Entry extends Var implements Comparable> {
Map wordPositions = ciMap(); // int array is sorted
Entry(A id) { super(id); }
public int compareTo(Entry e) {
return ((Comparable) get()).compareTo(e.get());
}
public boolean equals(Object o) {
return o instanceof Entry && get().equals(((Entry) o).get());
}
}
void init() {
if (entriesByWord != null) return;
entriesByWord = useHashMaps
? sortEntries ? multiSetMap_innerTreeSet() : new MultiSetMap()
: sortEntries ? ciMultiSetMap_innerTreeSet() : ciMultiSetMap();
}
List wordRanges(String text) {
return regexpFindRanges(regexp, text);
}
void add(A a, String text) {
init();
Entry e = new Entry(a);
if (useHashMaps) {
e.wordPositions = new HashMap();
text = upper(text);
}
if (entries.put(a, e) != null) throw fail("Double insertion");
MultiMap wordPositions = ciMultiMap();
for (IntRange r : wordRanges(text)) {
String word = substring(text, r);
wordPositions.put(word, r.start);
entriesByWord.put(word, e);
}
for (String word : keys(wordPositions))
e.wordPositions.put(word, toIntArray(wordPositions.get(word)));
}
Set> get(String word) { return entriesByWord.get(word); }
int numWords() { return entriesByWord.keysSize(); }
void doneAdding() {
if (entriesByWord_lists != null) return;
entriesByWord_lists = mapValues(__18 -> asList(__18),entriesByWord.data);
// TODO: release entriesByWord
}
Iterable>>lookupString_withPositions(String query, Object... __) {
boolean debug = boolPar("debug",__);
doneAdding();
if (useHashMaps) query = upper(query);
String _query = query;
List ranges = wordRanges(query);
if (empty(ranges)) return null;
int nRanges = l(ranges);
int iFirstComplete = first(ranges).start == 0 ? 1 : 0;
int iLastComplete = last(ranges).end == l(query) ? nRanges-1 : nRanges;
List words = map(ranges, r -> substring(_query, r));
List>> entriesAtIndex = map(words, word -> entriesByWord_lists.get(word));
if (iLastComplete >= iFirstComplete+1) {
int shortest = iFirstComplete, nBest = l(entriesAtIndex.get(shortest));
if (nBest == 0) { /*print("No results for " + words.get(shortest));*/ return emptyList(); }
for (int iWord = iFirstComplete+1; iWord < iLastComplete; iWord++) {
int n = l(entriesAtIndex.get(iWord));
if (n == 0) { /*print("No results for " + words.get(iWord));*/ return emptyList(); }
if (n < nBest) {
shortest = iWord;
nBest = n;
}
}
int _shortest = shortest;
Iterable> entries = sortEntries
? intersectMultipleSortedCollectionsI(subList(entriesAtIndex, iFirstComplete, iLastComplete))
: entriesAtIndex.get(shortest);
int startShortest = ranges.get(shortest).start;
String shortestWord = words.get(shortest); // not the shortest word, but the word with the shortest result list
/*if (debug)*/ print("shortest: " + shortestWord + ", words: " + zipTwoLists(words, lmap(__19 -> l(__19),entriesAtIndex)));
IntBuffer intBuffer = new IntBuffer();
return mapI_nonNulls_if1(entries, entry -> {
int[] positions = entry.wordPositions.get(shortestWord);
for (int iWord = iFirstComplete; iWord < iLastComplete; iWord++) {
{ if (iWord == _shortest) continue; }
IntRange r2 = ranges.get(iWord);
String word2 = words.get(iWord);
int[] positions2 = entry.wordPositions.get(word2);
if (positions2 == null) return null;
int ofs = startShortest-r2.start;
int len = l(positions);
positions = intersectSortedIntArrays_ofs_optimized2(positions, positions2, ofs, intBuffer);
print("Intersected " + len + "/" + l(positions2) + " => " + l(positions));
//if (debug) print("Got " + asList(positions));
if (empty(positions)) return null;
}
return pair(entry.get(), wrapIntArrayAsImmutableList_ofs(positions, -startShortest));
});
}
return null;
}
}
static TreeMap ciMap() {
return caseInsensitiveMap();
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static A get(List l, int idx) {
return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static B get(Map map, A key) {
ret map != null ? map.get(key) : null;
}*/
static A get(A[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
try {
if (o == null) return null;
if (o instanceof Class) return get((Class) o, field);
if (o instanceof Map)
return ((Map) o).get(field);
Field f = getOpt_findField(o.getClass(), field);
if (f != null) {
makeAccessible(f);
return f.get(o);
}
} catch (Exception e) {
throw asRuntimeException(e);
}
throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(String field, Object o) {
return get_raw(o, field);
}
static Object get_raw(Object o, String field) { try {
if (o == null) return null;
Field f = get_findField(o.getClass(), field);
makeAccessible(f);
return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
static Object get(Class c, String field) {
try {
Field f = get_findStaticField(c, field);
makeAccessible(f);
return f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static Field get_findStaticField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
Class _c = c;
do {
for (Field f : _c.getDeclaredFields())
if (f.getName().equals(field))
return f;
_c = _c.getSuperclass();
} while (_c != null);
throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static Object get(String field, Object o) {
return get(o, field);
}
static MultiSetMap multiSetMap_innerTreeSet() {
return new MultiSetMap() {
Set _makeEmptySet() { return new TreeSet(); }
};
}
static MultiSetMap ciMultiSetMap_innerTreeSet() { return ciMultiSetMap_innerTreeSet(null); }
static MultiSetMap ciMultiSetMap_innerTreeSet(Comparator innerComparator) {
MultiSetMap mm = new MultiSetMap() {
Set _makeEmptySet() { return new TreeSet(innerComparator); }
};
mm.data = ciMap();
return mm;
}
static MultiSetMap ciMultiSetMap() {
MultiSetMap mm = new MultiSetMap();
mm.data = ciMap();
return mm;
}
static List regexpFindRanges(String pat, String s) {
Matcher m = regexpMatcher(pat, s);
List l = new ArrayList();
while (m.find())
l.add(new IntRange(m.start(), m.end()));
return l;
}
static String upper(String s) {
return s == null ? null : s.toUpperCase();
}
static char upper(char c) {
return Character.toUpperCase(c);
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static MultiMap ciMultiMap() {
return caseInsensitiveMultiMap();
}
static String substring(String s, int x) {
return substring(s, x, strL(s));
}
static String substring(String s, int x, int y) {
if (s == null) return null;
if (x < 0) x = 0;
if (x >= s.length()) return "";
if (y < x) y = x;
if (y > s.length()) y = s.length();
return s.substring(x, y);
}
static String substring(String s, IntRange r) {
return r == null ? null : substring(s, r.start, r.end);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, l(l));
}
static Set keys(Map map) {
return map == null ? new HashSet() : map.keySet();
}
// convenience shortcut for keys_gen
static Set keys(Object map) {
return keys((Map) map);
}
static Set keys(MultiMap mm) {
return mm.keySet();
}
static Set keys(MultiSetMap mm) {
return mm.keySet();
}
static int[] toIntArray(Collection l) {
int[] a = new int[l(l)];
int i = 0;
if (a.length != 0) for (int x : l)
a[i++] = x;
return a;
}
static Map mapValues(Object func, Map map) {
Map m = similarEmptyMap(map);
for (Object key : keys(map))
m.put(key, callF(func, map.get(key)));
return m;
}
static Map mapValues(Map map, IF1 f) {
return mapValues(f, map);
}
static Map mapValues(IF1 f, Map map) {
return mapValues((Object) f, map);
}
static Map mapValues(Map map, Object func) {
return mapValues(func, map);
}
// unclear semantics as to whether return null on null
static ArrayList asList(A[] a) {
return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a));
}
static ArrayList asList(int[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (int i : a) l.add(i);
return l;
}
static ArrayList asList(float[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (float i : a) l.add(i);
return l;
}
static ArrayList asList(double[] a) {
if (a == null) return null;
ArrayList l = emptyList(a.length);
for (double i : a) l.add(i);
return l;
}
static ArrayList asList(Iterable s) {
if (s instanceof ArrayList) return (ArrayList) s;
ArrayList l = new ArrayList();
if (s != null)
for (A a : s)
l.add(a);
return l;
}
static ArrayList asList(Enumeration e) {
ArrayList l = new ArrayList();
if (e != null)
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
static boolean boolPar(ThreadLocal tl) {
return boolOptParam(tl);
}
// defaults to false
static boolean boolPar(Object[] __, String name) {
return boolOptParam(__, name);
}
static boolean boolPar(String name, Object[] __) {
return boolOptParam(__, name);
}
static boolean boolPar(String name, Map __) {
return boolOptParam(name, __);
}
static boolean boolPar(String name, Object[] params, boolean defaultValue) {
return optParam(params, name, defaultValue);
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
if (o instanceof byte[]) return empty((byte[]) o);
if (o == null) return true;
throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(IntRange r) { return r == null || r.empty(); }
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(Object o) {
return o == null ? 0
: o instanceof String ? l((String) o)
: o instanceof Map ? l((Map) o)
: o instanceof Collection ? l((Collection) o)
: o instanceof Object[] ? l((Object[]) o)
: o instanceof boolean[] ? l((boolean[]) o)
: o instanceof byte[] ? l((byte[]) o)
: o instanceof char[] ? l((char[]) o)
: o instanceof short[] ? l((short[]) o)
: o instanceof int[] ? l((int[]) o)
: o instanceof float[] ? l((float[]) o)
: o instanceof double[] ? l((double[]) o)
: o instanceof long[] ? l((long[]) o)
: (Integer) call(o, "size");
}
static int l(IntRange r) { return r == null ? 0 : r.length(); }
static Object first(Object list) {
return first((Iterable) list);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static A first(IterableIterator i) {
return first((Iterator) i);
}
static A first(Iterator i) {
return i == null || !i.hasNext() ? null : i.next();
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static Byte first(byte[] l) {
return empty(l) ? null : l[0];
}
static A last(List l) {
return empty(l) ? null : l.get(l.size()-1);
}
static char last(String s) {
return empty(s) ? '#' : s.charAt(l(s)-1);
}
static int last(int[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static double last(double[] a) {
return l(a) != 0 ? a[l(a)-1] : 0;
}
static A last(A[] a) {
return l(a) != 0 ? a[l(a)-1] : null;
}
static A last(Iterator it) {
A a = null;
while (it.hasNext()) { ping(); a = it.next(); }
return a;
}
static A last(Collection l) {
if (l == null) return null;
if (l instanceof List) return (A) last(((List) l));
if (l instanceof SortedSet) return (A) last(((SortedSet) l));
Iterator it = iterator(l);
A a = null;
while (it.hasNext()) { ping(); a = it.next(); }
return a;
}
static A last(SortedSet l) {
return l == null ? null : l.last();
}
static List map(Iterable l, Object f) { return map(f, l); }
static List map(Object f, Iterable l) {
List x = emptyList(l);
if (l != null) for (Object o : l)
x.add(callF(f, o));
return x;
}
static List map(Iterable l, F1 f) { return map(f, l); }
static List map(F1 f, Iterable l) {
List x = emptyList(l);
if (l != null) for (A o : l)
x.add(callF(f, o));
return x;
}
static List map(IF1 f, Iterable l) { return map(l, f); }
static List map(Iterable l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
x.add(f.get(o));
return x;
}
static List map(IF1 f, A[] l) { return map(l, f); }
static List map(A[] l, IF1 f) {
List x = emptyList(l);
if (l != null) for (A o : l)
x.add(f.get(o));
return x;
}
static List map(Object f, Object[] l) { return map(f, asList(l)); }
static List map(Object[] l, Object f) { return map(f, l); }
static List map(Object f, Map map) {
return map(map, f);
}
// map: func(key, value) -> list element
static List map(Map map, Object f) {
List x = new ArrayList();
if (map != null) for (Object _e : map.entrySet()) {
Map.Entry e = (Map.Entry) _e;
x.add(callF(f, e.getKey(), e.getValue()));
}
return x;
}
static List map(Map map, IF2 f) {
return map(map, (Object) f);
}
static ArrayList emptyList() {
return new ArrayList();
//ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
return emptyList(l(l));
}
// get correct type at once
static ArrayList emptyList(Class c) {
return new ArrayList();
}
// null elements are not supported
static , B extends Iterable> IterableIterator intersectMultipleSortedCollectionsI(List collections) {
if (empty(collections)) return emptyItIt();
return iteratorFromFunction_if0(new IF0() {
Iterator[] iterators = makeIteratorArray(collections);
int n = iterators.length;
A[] objects = (A[]) new Comparable[n];
boolean done = false;
{
// Grab first round of objects
for (int i = 0; i < n; i++)
if (step(i)) break;
}
// returns true if done
boolean step(int i) {
if (!iterators[i].hasNext())
{ done = true; return true; }
else {
objects[i] = iterators[i].next();
}
return false;
}
public A get() {
while (true) { ping();
if (done) return null;
// get min & max
A min = objects[0], max = objects[0];
for (int i = 1; i < n; i++) {
A o = objects[i];
if (min.compareTo(o) > 0) min = o;
if (max.compareTo(o) < 0) max = o;
}
// min = max? then return element
if (min == max) {
for (int i = 0; i < n; i++) if (step(i)) break;
return min;
}
// advance all to max
for (int i = 0; i < n; i++)
while (objects[i].compareTo(max) < 0)
if (step(i)) return null;
}
}
});
}
static List subList(List l, int startIndex) {
return subList(l, startIndex, l(l));
}
static List subList(int startIndex, int endIndex, List l) {
return subList(l, startIndex, endIndex);
}
static List subList(List l, int startIndex, int endIndex) {
if (l == null) return null;
int n = l(l);
startIndex = Math.max(0, startIndex);
endIndex = Math.min(n, endIndex);
if (startIndex >= endIndex) return ll();
if (startIndex == 0 && endIndex == n) return l;
return l.subList(startIndex, endIndex);
}
static List subList(List l, IntRange r) {
return subList(l, r.start, r.end);
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal