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.*;
// returns null if there are no letters in the query
// otherwise returns actual search result
class main {
static Iterable deepDoubleWordIndex_search(DoubleWordIndex> index, Map texts, String query, Object... __) {
boolean debug = boolPar("debug",__);
List ranges = index.wordRanges(query);
if (empty(ranges)) return null;
int nRanges = l(ranges);
Map> theMap = new HashMap(); // for every snippet, a map of string position to word index
// special case, just a single word in query
if (l(ranges) == 1 && first(ranges).start == 0 && first(ranges).end == l(query)) {
Set seen = new HashSet();
return nestedIterator(containingIC(index.index1.words(), query), fullWord ->
mapI_notNulls_if1(index.index1.get(fullWord), e -> addAndReturnIfNew(seen, e.get())));
}
Set baseSet = null;
/*if (int iWord = 1; i < nRanges-1; i++) { // go through all "full" words
IntRange r = ranges.get(iWord);
S word = substring(query, r);
Set> entries = index.index1.get(word);
if (baseSet == null) baseSet = ...
}*/
for (int iWord = 0; iWord < nRanges; iWord++) { // go through words in query
IntRange r = ranges.get(iWord);
String word = substring(query, r);
Collection l; // all matching words in index
WordIndex> indexToUse = index.index1;
if (r.start == 0) { // look for ending of word - use reverse index
l = prefixSubSet(index.index2.words(), reversed(word));
if (empty(l)) return emptyList();
if (debug) print("word=" + word + ", fullWords=" + l);
// special loop that accounts for length of actual word
for (String fullWord : l)
for (WithIntArray entry : index.index2.index.get(fullWord)) {
if (baseSet != null && !baseSet.contains(entry.get())) continue;
MultiSetMap msm = theMap.get(entry.get());
if (msm == null) theMap.put(entry.get(), msm = new MultiSetMap());
int ofs = l(fullWord)-l(word)-r.start;
for (int i : entry.array) {
int idx = i+ofs;
if (debug) print("Got idx " + idx);
if (idx >= 0)
msm.put(idx, iWord);
}
}
continue;
} else if (r.end == l(query)) { // look for start of word
l = prefixSubSet(index.index1.words(), word);
} else // look for complete word
l = ll(word);
if (empty(l)) return emptyList();
if (debug) print("word=" + word + ", fullWords=" + l);
for (String fullWord : l)
for (WithIntArray entry : indexToUse.index.get(fullWord)) {
if (baseSet != null && !baseSet.contains(entry.get())) continue;
if (debug) print("Got entry " + entry);
MultiSetMap msm = theMap.get(entry.get());
if (msm == null) theMap.put(entry.get(), msm = new MultiSetMap());
for (int i : entry.array) {
int idx = i-r.start;
if (debug) print("Got idx " + idx);
if (idx >= 0)
msm.put(idx, iWord);
}
}
}
if (debug) print("theMap size=" + l(theMap));
List out = new ArrayList();
theLoop: for (A snippet : keys( theMap)) { MultiSetMap msm = theMap.get(snippet);
if (debug) print("snippet " + snippet);
{ final Map> __0 = msm.data; for (int position : keys( __0)) { Set wordIndices = __0.get(position);
if (debug) print("position " + position + ": " + l(wordIndices) + "/" + nRanges);
if (l(wordIndices) == nRanges) {
out.add(snippet);
continue theLoop;
}
}}
}
return out;
}
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(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];
}
// TODO: clean up these type signatures?
static > IterableIterator nestedIterator(final Iterable c, final F1 makeInnerIterator) {
return nestedIterator(iterator(c), makeInnerIterator);
}
static > IterableIterator nestedIterator(Collection c, final IF1 makeInnerIterator) {
return nestedIterator(iterator(c), makeInnerIterator);
}
static > IterableIterator nestedIterator(Iterator it1, IF1 makeInnerIterator) {
return nestedIterator(it1, toF1(makeInnerIterator));
}
static > IterableIterator nestedIterator(final Iterator it1, final F1 makeInnerIterator) {
if (it1 == null || !it1.hasNext()) return emptyIterableIterator();
return iff(new F0() {
A a;
Iterator innerIterator;
{ nextOuter(); }
void nextOuter() {
a = it1.next();
innerIterator = callF(makeInnerIterator, a);
}
public Object get() {
while (true) { ping();
if (innerIterator.hasNext())
return innerIterator.next();
if (!it1.hasNext()) return endMarker();
nextOuter();
}
}
});
}
static > IterableIterator nestedIterator(IF1 makeInnerIterator, Iterator it1) {
return nestedIterator(it1, makeInnerIterator);
}
static > IterableIterator nestedIterator(IF1 makeInnerIterator, Collection l) {
return nestedIterator(l, makeInnerIterator);
}
static List containingIC(Collection l, final String x) {
List out = new ArrayList();
for (String s : unnull(l))
if (cic(s, x))
out.add(s);
return out;
}
static List containingIC(String x, Collection l) {
return containingIC(l, x);
}
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 NavigableSet prefixSubSet(NavigableSet set, String prefix) {
return set.subSet(prefix, true, prefix + Character.MAX_VALUE, true);
}
static List reversed(Collection l) {
return reversedList(l);
}
static List reversed(A[] l) {
return reversedList(asList(l));
}
static String reversed(String s) {
return reversedString(s);
}
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();
}
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