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 java.util.function.*;
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 java.awt.geom.*;
import javax.imageio.*;
import java.math.*;
import static x30_pkg.x30_util.DynamicObject;
class main {
static class ProbabilisticMachine {
transient TreeSetWithDuplicates < A > doneStates = new TreeSetWithDuplicates<>(byProbability());
transient TreeSetWithDuplicates < A > states = new TreeSetWithDuplicates<>(byProbability());
transient TreeSetWithDuplicates < A > steppableStates = new TreeSetWithDuplicates<>(byProbability());
transient TreeSetWithDuplicates < A > droppedStates = new TreeSetWithDuplicates<>(byProbability());
transient int stateCount;
boolean verbose = false;
double cutoffPercentage = 50;
Comparator byProbability() { return (a, b) -> cmp(b.probability, a.probability); }
abstract static class State {
ProbabilisticMachine machine;
int number;
State prev;
double probability = 100;
BasicLogicRule remainingRule;
public String toString() {
return toStringWithFields(this, "number", "probability") + stringIf(done(), " (done)");
}
boolean done() { return remainingRule == null; }
Object action() { return remainingRule == null ? null : remainingRule.lhs; }
void step() { if (!done()) runAction(action()); }
abstract void runAction(Object action);
abstract State emptyClone();
State prepareClone() {
State s = emptyClone();
copyFields(this, s, "machine", "probability");
s.prev = this;
s.remainingRule = optCast(BasicLogicRule.class, remainingRule.rhs);
return s;
}
}
void addState(A s) {
if (verbose) print("Adding state to machine " + this + ": " + s);
s.machine = this;
if (s.number == 0) s.number = ++stateCount;
if (s.probability < cutoffPercentage) { droppedStates.add(s); return; }
addToCollections(s, states, steppableStates);
if (s.done()) doneStates.add(s);
if (verbose) printStats();
}
boolean stepFirstUnstepped() {
A s = popFirst(steppableStates); if (s == null) return false;
{ s.step(); return true; }
}
void reset() {
clearAll(doneStates, states, steppableStates, droppedStates);
stateCount = 0;
}
void think() {
while (stepFirstUnstepped()) { ping(); }
}
List bestStates(int n) {
return takeFirst(n, doneStates);
}
void printStats() {
print("States: " + stats(states) + ", done: " + stats(doneStates) + ", steppable: " + stats(steppableStates) + ", dropped: " + stats(droppedStates));
}
String stats(TreeSetWithDuplicates ts) {
return l(ts) + (empty(ts) ? "" : " (best: " + iround(first(ts).probability) + ")");
}
}
static int cmp(Number a, Number b) {
return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue());
}
static int cmp(double a, double b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(int a, int b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(long a, long b) {
return a < b ? -1 : a == b ? 0 : 1;
}
static int cmp(Object a, Object b) {
if (a == null) return b == null ? 0 : -1;
if (b == null) return 1;
return ((Comparable) a).compareTo(b);
}
static String toStringWithFields(Object o, String... fields) {
return stdToStringWithFields(o, fields);
}
static String stringIf(boolean b, String s) {
return stringIfTrue(b, s);
}
static String stringIf(String s, boolean b) {
return stringIf(b, s);
}
static int done_minPrint = 10;
static long done(long startTime, String desc) {
long time = now()-startTime;
if (time >= done_minPrint)
print(desc + " [" + time + " ms]");
return time;
}
static long done(String desc, long startTime) {
return done(startTime, desc);
}
static long done(long startTime) {
return done(startTime, "");
}
static A copyFields(Object x, A y, String... fields) {
if (empty(fields)) { // assume we should copy all fields
Map map = objectToMap(x);
for (String field : map.keySet())
setOpt(y, field, map.get(field));
} else
for (String field : fields) {
Object o = getOpt(x, field);
if (o != null)
setOpt(y, field, o);
}
return y;
}
static A copyFields(Object x, A y, Collection fields) {
return copyFields(x, y, asStringArray(fields));
}
static A optCast(Class c, Object o) {
return isInstance(c, o) ? (A) o : null;
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static boolean printAlsoToSystemOut = true;
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