Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

1914
LINES

< > BotCompany Repo | #704 // IOIOI Processor (v11)

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (5537L/37K/109K).

1  
!636
2  
!quickmain
3  
!auto-import
4  
!standard functions
5  
!quicknew
6  
!1000346 // use "case" as a variable name
7  
!688 // buf.isEmpty
8  
!class JavaTok
9  
!1000381 // L<S>
10  
!697 // "*()" constructor syntax, v2
11  
12  
import java.lang.reflect.*;
13  
import java.math.*; // BigInteger
14  
import java.text.DecimalFormat;
15  
import java.lang.management.*; // for time measurement
16  
17  
!include #1000451 // class _x18 modified for Android
18  
19  
interface Function {
20  
  public Object process(Object in);
21  
  public void toJava_process(Code code);
22  
}
23  
24  
interface ReversibleFunction extends Function {
25  
  public Object unprocess(Object in);
26  
  public void toJava_unprocess(Code code);
27  
}
28  
29  
// generic learner (works on objects)
30  
interface Learner {
31  
  public void processInOut(Object in, Object out);
32  
  public Object processIn(Object in);
33  
  public void toJava(Code code);
34  
  public void tryAgain();
35  
}
36  
37  
abstract class Base {
38  
  void printVars() {
39  
    new StringBuilder buf;
40  
    Field[] fields = getClass().getDeclaredFields();
41  
    for (Field field : fields) {
42  
      if ((field.getModifiers() & Modifier.STATIC) != 0)
43  
        continue;
44  
      Object value;
45  
      try {
46  
        value = field.get(this);
47  
      } catch (Exception e) {
48  
        value = "?";
49  
      }
50  
      
51  
      if (!buf.isEmpty()) buf.append(", ");
52  
      buf.append(field.getName() + "=" + value);
53  
    }
54  
    System.out.println(buf.toString());
55  
  }
56  
}
57  
58  
abstract class LearnerImpl extends Base implements Learner {
59  
  public void tryAgain() {
60  
    throw new RuntimeException("No try again");
61  
  }
62  
  
63  
  public void toJava(Code code) {
64  
    main.todo();
65  
  }
66  
}
67  
68  
class Code {
69  
  new StringBuilder buf;
70  
  String var = "in";
71  
  String indent = "";
72  
  new List<String> translators;
73  
  new List<String> varStack;
74  
  int varCounter;
75  
  
76  
  *() {
77  
    translators.add("!636");
78  
  }
79  
  
80  
  void line(String line) {
81  
    buf.append(indent).append(line).append('\n');
82  
  }
83  
  
84  
  void indent() {
85  
    indent += "  ";
86  
  }
87  
  
88  
  void unindent() {
89  
    indent = indent.substring(0, indent.length()-2);
90  
  }
91  
  
92  
  void translators(String... ids) {
93  
    for (String id : ids)
94  
      if (! translators.contains(id)) // space is needed otherwise translator 636 is fooled :)
95  
        translators.add(id);
96  
  }
97  
  
98  
  String getTranslators() {
99  
    // TODO: We should really fix the "standard functions" translator
100  
    // to properly find the main class.
101  
    //
102  
    // As a hack, we move it upwards (before classes adding)
103  
    int i = translators.indexOf("!standard functions");
104  
    if (i >= 0) {
105  
      translators.remove(i);
106  
      translators.add(0, "!standard functions");
107  
    }
108  
    
109  
    return main.fromLines(translators);
110  
  }
111  
112  
  String s() {
113  
    return "((String) " + var + ")";
114  
  }
115  
  
116  
  String list() {
117  
    return "((List) " + var + ")";
118  
  }
119  
  
120  
  void assign(String exp) {
121  
    line(var + " = " + exp + ";");
122  
  }
123  
  
124  
  void newVar() {
125  
    varStack.add(var);
126  
    var = "_v" + (++varCounter);
127  
    line("Object " + var + ";");
128  
  }
129  
  
130  
  void oldVar() {
131  
    var = varStack.get(varStack.size()-1);
132  
    varStack.remove(varStack.size()-1);
133  
  }
134  
}
135  
136  
main {
137  
  static Object androidContext;
138  
  
139  
  static new List<Case> cases;
140  
  static new HashMap<String, Case> casesByID;
141  
  static boolean testJava = false, showFails, execTasks = false;
142  
  static new (Hash)Set<String> parseErrors;
143  
  static int caseIdx;
144  
  static new (Hash)Set<Class> debuggedClasses;
145  
146  
  psvm {
147  
    _x18.androidContext = androidContext;
148  
    long startTime = System.currentTimeMillis();
149  
    
150  
    new List<String> snippetIDs;
151  
    new List<String> inputs;
152  
    
153  
    for (int i = 0; i < args.length; i++) {
154  
      String arg = args[i];
155  
      if (arg.equals("debug"))
156  
        debugOn(args[++i]);
157  
      else if (arg.equals("in")) {
158  
        String in = args[++i];
159  
        System.out.println("in=" + quote(in));
160  
        String quoteUnquote = unquote("\"" + in + "\"");
161  
        System.out.println("now in=" + quote(quoteUnquote));
162  
        inputs.add(quoteUnquote);
163  
      } else if (arg.equals("-notestjava"))
164  
        testJava = false;
165  
      else if (arg.equals("-testjava"))
166  
        testJava = true;
167  
      else if (arg.equals("-withexec"))
168  
        execTasks = true;
169  
      else if (arg.equals("-showfails"))
170  
        showFails = true;
171  
      else if (isSnippetID(arg))
172  
        snippetIDs.add(arg);
173  
      else
174  
        System.err.println("Unknown argument: " + arg + ", ignoring");
175  
    }
176  
    
177  
    if (snippetIDs.isEmpty())
178  
      parse(null);
179  
    
180  
    for (String snippetID : snippetIDs)
181  
      try {
182  
        Case case = parse(snippetID);
183  
        case.halfExamples.addAll(inputs);
184  
      } catch (Throwable e) {
185  
        e.printStackTrace();
186  
        parseErrors.add(snippetID);
187  
      }
188  
    
189  
    int solved = 0, n = cases.size(), goodJava = 0;
190  
    for (caseIdx = 0; caseIdx < n; caseIdx++) {
191  
      Case case = cases.get(caseIdx);
192  
      try {
193  
        calculate(case);
194  
      } catch (Throwable e) {
195  
        e.printStackTrace();
196  
      }
197  
      if (case.winner != null)
198  
        ++solved;
199  
      if (case.goodJava)
200  
        ++goodJava;
201  
      if (caseIdx+1 == solved)
202  
        System.out.println((caseIdx+1) + " case(s) processed & solved.");
203  
      else
204  
        System.out.println((caseIdx+1) + " case(s) processed, " + solved + " solved.");
205  
      if (testJava && goodJava < solved)
206  
        System.out.println((solved-goodJava) + " case(s) with BAD JAVA.");
207  
    }
208  
209  
    print ""    
210  
    print "----"
211  
212  
    List<Case> sorted = casesSortedByID();
213  
    boolean allSolved = solved == n;
214  
    if (solved != 0) {
215  
      System.out.println();
216  
      System.out.print("Solved: ");
217  
      for (Case case : sorted)
218  
        if (case.winner != null)
219  
          System.out.print(case.id + " ");
220  
      System.out.println();
221  
    }
222  
    if (testJava && solved > goodJava) {
223  
      System.out.println();
224  
      System.out.print("Bad Java: ");
225  
      for (Case case : sorted)
226  
        if (case.winner != null && !case.goodJava)
227  
          System.out.print(case.id + " ");
228  
      System.out.println();
229  
    }
230  
    if (!allSolved) {
231  
      System.out.println();
232  
      System.out.print("Unsolved: ");
233  
      for (Case case : sorted)
234  
        if (case.winner == null)
235  
          System.out.print(case.id + " ");
236  
      System.out.println();
237  
    }
238  
    if (!parseErrors.isEmpty()) {
239  
      System.out.print("\nParse errors: ");
240  
      for (String id : parseErrors)
241  
          System.out.print(id + " ");
242  
      System.out.println();
243  
    }
244  
    System.out.println();
245  
    if (allSolved && testJava && goodJava < solved)
246  
      System.out.println("ALL SOLVED (" + solved + "), but some BAD JAVA.");
247  
    else {
248  
      System.out.println(allSolved ? "ALL SOLVED (" + solved + ")" : "Solved " + solved + " out of " + n + ".");
249  
      if (testJava)
250  
        if (goodJava == solved)
251  
          System.out.println("All Java code OK" + (allSolved ? "" : " (for solved cases)") + ".");
252  
        else
253  
          System.out.println("Some bad Java.");
254  
      else
255  
        System.out.println("Java not tested.");
256  
    }
257  
    print ""
258  
    
259  
    /*long time = getUserTime();
260  
    if (time >= 0)
261  
      System.out.println("User time: " + formatDouble(time/1e9, 3) + "s");*/
262  
      
263  
    long time = System.currentTimeMillis()-startTime;
264  
    System.out.println("Real time: " + formatDouble(time/1e3, 3) + "s");
265  
  }
266  
  
267  
  public static String formatDouble(double d, int digits) {
268  
    String format = "0.";
269  
    for (int i = 0; i < digits; i++) format += "#";
270  
    String s = new DecimalFormat(format).format(d);
271  
    return s.replace(',', '.'); // hack german -> english
272  
  }
273  
  
274  
  /** Get user time in nanoseconds. */
275  
  public static long getUserTime( ) {
276  
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
277  
    return bean.isCurrentThreadCpuTimeSupported() ?
278  
      bean.getCurrentThreadUserTime() : -1L;
279  
  }
280  
  
281  
  static class Case {
282  
    String id;
283  
    new List<String[]> fullExamples;
284  
    new List<String> halfExamples;
285  
    List<String[]> examples1, examples2;
286  
    Learner winner;
287  
    new RunnersUp runnersUp;
288  
    boolean goodJava;
289  
    List<Case> combined;
290  
    int splitPoint = -1;
291  
    
292  
    // stats
293  
    int learnersTried, retries;
294  
295  
    void split() {    
296  
      if (examples1 != null)
297  
        return; // already done
298  
      if (fullExamples.size() < 2)
299  
        throw new RuntimeException("Too few examples (" + fullExamples.size() + ")");
300  
      if (splitPoint < 0)
301  
        splitPoint = fullExamples.size()-1;
302  
      System.out.println("Full examples: " + fullExamples.size() + ", splitPoint: " + splitPoint + ", half examples: " + halfExamples.size());
303  
      examples1 = fullExamples.subList(0, splitPoint);
304  
      examples2 = fullExamples.subList(splitPoint, fullExamples.size());
305  
    }
306  
    
307  
    void add(Case case) {
308  
      combined.add(case);
309  
      fullExamples.addAll(case.fullExamples);
310  
      halfExamples.addAll(case.halfExamples);
311  
    }
312  
    
313  
    Object processIn(Object in) {
314  
      return winner.processIn(in);
315  
    }
316  
  }
317  
318  
  static Case parse(String arg) tex {
319  
   try {
320  
    new Case case;
321  
    String text;
322  
    if (arg != null) {
323  
      if (casesByID.containsKey(arg))
324  
        return casesByID.get(arg);
325  
        
326  
      if (arg.startsWith("Combine")) {
327  
        case.id = "Combine";
328  
        case.combined = new ArrayList<Case>();
329  
        List<String> tok = JavaTok.split(arg);
330  
        new List<String> ids;
331  
        for (int i = 5; i < tok.size(); i += 6) { // skip # and "and"
332  
          Case case2 = parse("#" + tok.get(i));
333  
          case.id += " #" + tok.get(i);
334  
          cases.remove(case2);
335  
          case.add(case2);
336  
        }
337  
        addCase(case);
338  
        return case;
339  
      } else if (isSnippetID(arg)) {
340  
        case.id = arg;
341  
        text = loadSnippet(arg);
342  
      } else {
343  
        case.id = "direct";
344  
        text = arg;
345  
      }
346  
    } else {
347  
      case.id = "input.txt";
348  
      text = loadTextFile("input/input.txt", null);
349  
      if (text == null) {
350  
        //case.id = "#2000455";  // example input
351  
        case.id = "#681"; // a collection of "all cases"!
352  
        text = loadSnippet(case.id);
353  
      }
354  
    }
355  
    
356  
    // it's a collection of cases!
357  
    if (text.trim().startsWith("#") || text.trim().startsWith("Combine")) {
358  
      for (String line : toLines(text))
359  
        if (line.trim().length() != 0)
360  
          parse(line.trim());
361  
      return null;
362  
    }
363  
    
364  
    // it's a "Continue:" task - transform to I/O format
365  
    if (text.trim().startsWith("Continue:")) {
366  
      List<String> lines = toLines(text);
367  
      new StringBuilder buf;
368  
      for (int i = 1; i < lines.size(); i++) {
369  
        buf.append("In: " + quote("" + i) + "\n");
370  
        buf.append("Out: " + quote(lines.get(i)) + "\n");
371  
      }
372  
      int numAsking = 3;
373  
      for (int i = lines.size(); i < lines.size()+numAsking; i++)
374  
        buf.append("In: " + quote("" + i) + "\n");
375  
      text = buf.toString();
376  
    }
377  
      
378  
    // it's an "Execute." task - run Java(X) and transform to I/O format
379  
    if (text.trim().startsWith("Execute.")) {
380  
      if (!execTasks) return null;
381  
      List<String> tok = JavaTok.split(text);
382  
      new StringBuilder buf;
383  
      for (int i = 5; i < tok.size(); i += 2) {
384  
        if (tok.get(i).equals("-") && tok.get(i+2).equals("-")) {
385  
          i += 2;
386  
          buf.append("--\n");
387  
        } else {
388  
          String code = unquote_fixSpaces(tok.get(i));
389  
          String result = execute("!636\n" + code);
390  
          buf.append("In: " + quote(code) + "\n");
391  
          buf.append("Out: " + quote(result) + "\n");
392  
        }
393  
      }
394  
      text = buf.toString();
395  
    }
396  
      
397  
    System.out.println(text);
398  
    String in = null, out = null;
399  
    
400  
    List<String> tok = JavaTok.split(text);
401  
    for (int i = 1; i < tok.size(); i += 2) {
402  
      String t = tok.get(i), t2 = i+2 < tok.size() ? tok.get(i+2) : "";
403  
      if (t.equals("-") && t2.equals("-")) {
404  
        i += 2;
405  
        case.splitPoint = case.fullExamples.size();
406  
        //System.out.println("t=" + t + ", t2= " + t2);
407  
      } else if (t.toUpperCase().startsWith("I") && t2.equals("-") && tok.get(i+4).toUpperCase().equals("DOC") && tok.get(i+6).equals(":")) { // "In-Doc:"
408  
        if (in != null)
409  
          case.halfExamples.add(in);
410  
        i += 8;
411  
        int j = findNextLine(tok, i);
412  
        String inID = unquote_fixSpaces(JavaTok.join(tok.subList(i, j-1)));
413  
        in = loadSnippet(inID);
414  
        i = j-2;
415  
        out = null;
416  
      } else if (t.toUpperCase().startsWith("I") && t2.equals(":")) { // "In:" or "I:"
417  
        if (in != null)
418  
          case.halfExamples.add(in);
419  
        i += 4;
420  
        int j = findNextLine(tok, i);
421  
        in = unquote_fixSpaces(JavaTok.join(tok.subList(i, j-1)));
422  
        i = j-2;
423  
        out = null;
424  
      } else if (t.toUpperCase().startsWith("O") && t2.equals(":")) { // "Out: " or "O: "
425  
        i += 4;
426  
        int j = findNextLine(tok, i);
427  
        out = unquote_fixSpaces(JavaTok.join(tok.subList(i, j-1)));
428  
        i = j-2;
429  
        if ((in + out).indexOf('\t') >= 0)
430  
          System.err.println("WARNING: Tab character used!");
431  
        System.out.println(quote(in) + " => " + quote(out));
432  
        case.fullExamples.add(new String[] {in, out});
433  
        in = out = null;
434  
      } else {
435  
        int j = findNextLine(tok, i);
436  
        String line = JavaTok.join(tok.subList(i, j-1));
437  
        i = j-2;
438  
        System.out.println("-- Ignoring line: " + line);
439  
      }
440  
    }
441  
    
442  
    if (in != null)
443  
      case.halfExamples.add(in);
444  
    addCase(case);
445  
    return case;
446  
   } catch (Throwable e) {
447  
    parseErrors.add(arg);
448  
    e.printStackTrace();
449  
    return null;
450  
   }
451  
  }
452  
  
453  
  static String unquote_fixSpaces(String s) {
454  
    String _ = unquote(s);
455  
    if (s.startsWith("[["))
456  
      _ = fixSpaces(_);
457  
    return _;
458  
  }
459  
  
460  
  // remove invisible spaces at end of line - this will otherwise confuse the engine(s) greatly...
461  
  static String fixSpaces(String s) {
462  
    System.out.println(quote(s));
463  
    s = s.replaceAll("[\t ]+(\r?\n)", "$1");
464  
    s = s.replaceAll("[\t ]+$", "");
465  
    //System.out.println("_fixSpaces => " + quote(s));
466  
    return s;
467  
  }
468  
  
469  
  // i is a code-token (odd index)
470  
  // return value is also a code token, or end of list
471  
  static int findNextLine(List<String> tok, int i) {
472  
    while (i < tok.size() && tok.get(i-1).indexOf('\n') < 0)
473  
      i += 2;
474  
    return i;
475  
  }
476  
  
477  
  static void addCase(Case case) {
478  
    cases.add(case);
479  
    casesByID.put(case.id, case);
480  
  }
481  
  
482  
  static void calculate(Case case) tex {
483  
    System.out.println("\n== CASE " + case.id + " ==");
484  
    
485  
    case.split();
486  
    Learner learner = findOKLearner(case);
487  
    if (learner == null) {
488  
      String stat = "";
489  
      if (case.retries != 0) stat = " + " + case.retries + " retries";
490  
      System.out.println("\nProblem not solved (" + case.learnersTried + " learners tried" + stat + ")");
491  
      RunnersUp ru = case.runnersUp;
492  
      if (ru != null && ru.winner != null)
493  
        System.out.println("Closest result: " + quote(ru.bestResult) + " instead of " + quote(ru.expected) + " (score " + ru.bestScore + ") by " + structure(ru.winner));
494  
    } else {
495  
      print "\nSolved!"
496  
      print(". " + structure(learner));
497  
      case.winner = learner;
498  
      new Code code;
499  
      if (testJava) try {
500  
        learner.toJava(code);
501  
502  
        if (testJava)
503  
          testJava(case, code); // prints "GOOD JAVA" or "BAD JAVA"
504  
        else
505  
          print "Java:"
506  
          
507  
        System.out.println(indent("  ", code.getTranslators()));
508  
        System.out.println(indent("  ", code.buf.toString()));
509  
      } catch (Throwable e) {
510  
        print "BAD JAVA"
511  
      }
512  
        
513  
      for (String in : case.halfExamples) {
514  
        Object out = learner.processIn(in);
515  
        System.out.println(quote(in) + " =>! " + quote((String) out));
516  
      }
517  
    }
518  
  }
519  
  
520  
  static Learner findOKLearner(Case case) tex {
521  
    for (Learner learner : makeLearners()) try {
522  
      if (learnerOK(learner, case))
523  
        return learner;
524  
    } catch (Throwable e) {
525  
      if (showFails)
526  
        e.printStackTrace();
527  
    }
528  
    
529  
    if (case.combined != null) {
530  
      Case switchCase = makeSwitchCase(case);
531  
      calculate(switchCase);
532  
      Learner learner = switchCase.winner;
533  
      if (learner != null)
534  
        return new LSwitch(case, learner);
535  
    }
536  
    
537  
    return null;
538  
  }
539  
  
540  
  static Case makeSwitchCase(Case case) {
541  
    int i = 0;
542  
    Case s = new Case();
543  
    s.id = "Switch " + case.id;
544  
    s.examples1 = new ArrayList<String[]>();
545  
    s.examples2 = new ArrayList<String[]>();
546  
    for (Case c : case.combined) {
547  
      ++i;
548  
      for (String[] e : c.examples1)
549  
        s.examples1.add(new String[] {e[0], String.valueOf(i)});
550  
      for (String[] e : c.examples2)
551  
        s.examples2.add(new String[] {e[0], String.valueOf(i)});
552  
      for (String[] e : c.fullExamples)
553  
        s.fullExamples.add(new String[] {e[0], String.valueOf(i)});
554  
    }
555  
    return s;
556  
  }
557  
  
558  
  static boolean learnerOK(Learner learner, Case case) {
559  
    String[] _e = null;
560  
    try {
561  
      if (case.examples1 == null)
562  
        fail("Case not calculated: " + case.id);
563  
        
564  
      ++case.learnersTried;
565  
      for (String[] e : case.examples1) {
566  
        _e = e;
567  
        learner.processInOut(e[0], e[1]);
568  
      }
569  
      
570  
      // full validation against all examples
571  
      int retry = 0;
572  
      retryLoop: while (true) {
573  
        for (String[] e : case.fullExamples) {
574  
          _e = e;
575  
          String out = (String) learner.processIn(e[0]);
576  
          if (!e[1].equals(out)) {
577  
          
578  
            if (case.runnersUp != null)
579  
              case.runnersUp.add(e[1], out, leven(out, e[1]), learner);
580  
              
581  
            if (showFails)
582  
              System.out.println("[fail] " + structure(learner) + " on " + quote(e[0]) + " - got: " + quote(out) + " rather than: " + quote(e[1]));
583  
            ++retry;
584  
            ++case.retries;
585  
            if (retry % 1000 == 0)
586  
              System.err.println("Retry " + retry);
587  
            learner.tryAgain();
588  
            continue retryLoop;
589  
          }
590  
        }
591  
        return true;  // all test examples passed
592  
      }
593  
    } catch (Throwable e) {
594  
      if (debuggedClasses.contains(learner.getClass()) || showFails) {
595  
        e.printStackTrace();
596  
        System.err.println("[fail] " + structure(learner) + " on " + (_e == null ? "?" : quote(_e[0])) + " - " + e);
597  
      }
598  
      return false;
599  
    }
600  
  }
601  
  
602  
  static boolean validate(String[] example, Learner learner) {
603  
    try {
604  
      String out = (String) learner.processIn(example[0]);
605  
      if (!example[1].equals(out)) {
606  
          //System.out.println("[fail] " + learner + " on " + quote(e[0]) + " - got: " + quote(out) + " rather than: " + quote(e[1]));
607  
          return false;
608  
        }
609  
      return true;
610  
    } catch (Throwable e) {
611  
      silentException(e);
612  
      return false;
613  
    }
614  
  }
615  
  
616  
  static void silentException(Throwable e) {
617  
  }
618  
  
619  
  /* XXX - important part */
620  
  static Iterable<Learner> makeLearners() {
621  
    new List<Learner> list;
622  
    list.addAll(level1());
623  
    list.add(new LBox(new LMulti(level1())));
624  
    list.add(new LBox2(new LMulti(level1())));
625  
    
626  
    list.add(new LChange(new FCommonPrefix(), new LOutPattern()));
627  
    list.add(new LChange(new FCommonSuffix(), new LOutPattern()));
628  
    
629  
    list.add(new LEmptyBox(new LMulti(level1())));
630  
    
631  
    list.add(new LChange(new RFToLines(), new LFixedFunction(new FLength())));
632  
    
633  
    // for #1000455
634  
    list.add(new LFindOutInIn(new LFixedSubstring()));
635  
636  
    return list;
637  
  }
638  
  
639  
  static List<Learner> level1() {
640  
    new List<Learner> list;
641  
    list.add(new LId()); // always good to have as included learner
642  
    list.add(new LPrefixSuffix());
643  
    list.add(new LSplitInput(new LOutPattern()));
644  
    list.add(new LInputPattern());
645  
    list.add(new LFixed());
646  
    list.add(new LBoth(new RFJavaTok(), new LEach(new LFixedFunction(new EscapeCase()))));
647  
    list.add(new LCharShift());
648  
    list.add(new LOutSuffix(new LFirst(new LCharShift())));
649  
    
650  
    list.add(new LChange(new RFJavaTok(), new LMulti(
651  
      new LChange(new FStringsOnly(), new LGetListElement()),
652  
      new LChange(new FNumbersOnly(), new LMath()))
653  
    ));
654  
    
655  
    // TODO - for #1000378
656  
    list.add(new LChange(new RFJavaTok(), new LDistinguishList(new FIsString())));
657  
    
658  
    list.add(new LFixedSubstring());
659  
    
660  
    // of no use now it seems
661  
    // list.add(new LTryPrevious());
662  
    
663  
    return list;
664  
  }
665  
  
666  
  public static String unquote(String s) {
667  
    if (s.startsWith("[[") && s.endsWith("]]"))
668  
      return s.substring(2, s.length()-2);
669  
    else if (s.startsWith("\"") && s.endsWith("\"") && s.length() > 1)
670  
      //return s.substring(1, s.length()-1).replace("\\\"", "\"").replace("\\\\", "\\");
671  
      return unescapeJavaString(s.substring(1, s.length()-1));
672  
    else
673  
      return s; // return original
674  
  }
675  
  
676  
  /** from: http://stackoverflow.com/questions/3537706/howto-unescape-a-java-string-literal-in-java,
677  
      or: https://gist.github.com/uklimaschewski/6741769
678  
      
679  
      Thanks!
680  
  */
681  
  public static String unescapeJavaString(String st) {
682  
    StringBuilder sb = new StringBuilder(st.length());
683  
684  
    for (int i = 0; i < st.length(); i++) {
685  
        char ch = st.charAt(i);
686  
        if (ch == '\\') {
687  
            char nextChar = (i == st.length() - 1) ? '\\' : st
688  
                    .charAt(i + 1);
689  
            // Octal escape?
690  
            if (nextChar >= '0' && nextChar <= '7') {
691  
                String code = "" + nextChar;
692  
                i++;
693  
                if ((i < st.length() - 1) && st.charAt(i + 1) >= '0'
694  
                        && st.charAt(i + 1) <= '7') {
695  
                    code += st.charAt(i + 1);
696  
                    i++;
697  
                    if ((i < st.length() - 1) && st.charAt(i + 1) >= '0'
698  
                            && st.charAt(i + 1) <= '7') {
699  
                        code += st.charAt(i + 1);
700  
                        i++;
701  
                    }
702  
                }
703  
                sb.append((char) Integer.parseInt(code, 8));
704  
                continue;
705  
            }
706  
            switch (nextChar) {
707  
            case '\\':
708  
                ch = '\\';
709  
                break;
710  
            case 'b':
711  
                ch = '\b';
712  
                break;
713  
            case 'f':
714  
                ch = '\f';
715  
                break;
716  
            case 'n':
717  
                ch = '\n';
718  
                break;
719  
            case 'r':
720  
                ch = '\r';
721  
                break;
722  
            case 't':
723  
                ch = '\t';
724  
                break;
725  
            case '\"':
726  
                ch = '\"';
727  
                break;
728  
            case '\'':
729  
                ch = '\'';
730  
                break;
731  
            // Hex Unicode: u????
732  
            case 'u':
733  
                if (i >= st.length() - 5) {
734  
                    ch = 'u';
735  
                    break;
736  
                }
737  
                int code = Integer.parseInt(
738  
                        "" + st.charAt(i + 2) + st.charAt(i + 3)
739  
                                + st.charAt(i + 4) + st.charAt(i + 5), 16);
740  
                sb.append(Character.toChars(code));
741  
                i += 5;
742  
                continue;
743  
            }
744  
            i++;
745  
        }
746  
        sb.append(ch);
747  
    }
748  
    return sb.toString();
749  
  }
750  
751  
public static String quote(String s) {
752  
    if (s == null) return "null";
753  
    return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
754  
  }
755  
  
756  
  static String indent(String indent, String s) {
757  
    return indent + s.replace("\n", "\n" + indent);
758  
  }
759  
  
760  
  static Class<?> getClass(String name) {
761  
    try {
762  
      return Class.forName(name);
763  
    } catch (ClassNotFoundException e) {
764  
      return null;
765  
    }
766  
  }
767  
  
768  
  static void debugOn(String name) {
769  
    try {
770  
      Class c = getClass("main$" + name);
771  
      if (c == null) c = getClass(name);
772  
      debuggedClasses.add(c);
773  
      Field field;
774  
      while (true)
775  
        try {
776  
          field = c.getDeclaredField("debug");
777  
          break;
778  
        } catch  (NoSuchFieldException e) {
779  
          c = c.getSuperclass();
780  
        }
781  
      field.setBoolean(null, true);
782  
    } catch (Exception e) {
783  
      e.printStackTrace();
784  
      System.err.println("Cannot debug class " + name);
785  
    }
786  
  }
787  
  
788  
  // splits the input at some point, takes only one part
789  
  static class LSplitInput extends LearnerImpl {
790  
    int splitIdx = 1; // split after first character
791  
    Learner baseLearner;
792  
    
793  
    LSplitInput(Learner baseLearner) {
794  
      this.baseLearner = baseLearner;
795  
    }
796  
    
797  
    public void processInOut(Object _in, Object _out) {
798  
      String in = (String) _in, out = (String) _out;
799  
      in = in.substring(splitIdx);
800  
      baseLearner.processInOut(in, out);
801  
    }
802  
    
803  
    public Object processIn(Object _in) {
804  
      String in = (String) _in;
805  
      in = in.substring(splitIdx);
806  
      return baseLearner.processIn(in);
807  
    }
808  
    
809  
    public void toJava(Code code) {
810  
      if (splitIdx != 0)
811  
        code.line(code.var + " = ((String) " + code.var + ").substring(" + splitIdx + ");");
812  
      baseLearner.toJava(code);
813  
    }
814  
  }
815  
816  
  static class FDropFirstLine implements Function {
817  
    public Object process(Object _in) {
818  
      String in = (String)_in;
819  
      return in.substring(in.indexOf('\n')+1);
820  
    }
821  
    
822  
    public void toJava_process(Code code) {
823  
      todo();
824  
    }
825  
  }
826  
  
827  
  // removes common suffix from out, delegates to base learner
828  
  static class LOutSuffix extends LearnerImpl {
829  
    String suffixOut = "";
830  
    Learner baseLearner;
831  
    
832  
    LOutSuffix(Learner baseLearner) {
833  
      this.baseLearner = baseLearner;
834  
    }
835  
    
836  
    public void processInOut(Object _in, Object _out) {
837  
      String in = (String) _in, out = (String) _out;
838  
      if (out.endsWith("!"))
839  
        suffixOut = "!";
840  
      if (out.endsWith(suffixOut))
841  
        out = out.substring(0, out.length()-suffixOut.length());
842  
      
843  
      baseLearner.processInOut(in, out);
844  
    }
845  
    
846  
    public Object processIn(Object _in) {
847  
      String in = (String) _in;
848  
      return baseLearner.processIn(in) + suffixOut;
849  
    }
850  
    
851  
    public void toJava(Code code) {
852  
      baseLearner.toJava(code);
853  
      if (suffixOut.length() != 0)
854  
        code.line(code.var + " = " + code.s() + "+" + quote(suffixOut) + ";");
855  
    }
856  
  }
857  
  
858  
  // if input appears in output in fixed pattern
859  
  static class LOutPattern extends LearnerImpl {
860  
    static boolean debug;
861  
    String pattern = "%!%";
862  
863  
    public void processInOut(Object _in, Object _out) {
864  
      String in = (String) _in, out = (String) _out;
865  
      pattern = out.replace(in, "%!%");
866  
      if (debug)
867  
        System.out.println("LOutPattern: in=" + quote(in) + ", out=" + quote(out) + ", pattern=" + quote(pattern));
868  
    }
869  
    
870  
    public String processIn(Object _in) {
871  
      String in = (String) _in;
872  
      return pattern.replace("%!%", in);
873  
    }
874  
    
875  
    public void toJava(Code code) {
876  
      code.line(code.var + " = " + quote(pattern) + ".replace(" + quote("%!%") + ", (String) " + code.var + ");");
877  
    }
878  
  }
879  
  
880  
  // simplets learner - only knows the "id" function
881  
  static class LId extends LearnerImpl {
882  
    public void processInOut(Object in, Object out) {
883  
    }
884  
    
885  
    public Object processIn(Object in) {
886  
      return in;
887  
    }
888  
    
889  
    public void toJava(Code code) {
890  
    }
891  
  }
892  
  
893  
  // learns to exchange common prefixes and suffixes
894  
  static class LPrefixSuffix extends LearnerImpl {
895  
    static boolean debug;
896  
    String prefixIn, suffixIn, prefixOut, suffixOut;
897  
    
898  
    public void processInOut(Object _in, Object _out) {
899  
      String in = (String) _in, out = (String) _out;
900  
      updateIn(in);
901  
      prefixOut = prefixOut == null ? out : commonPrefix(prefixOut, out);
902  
      suffixOut = suffixOut == null ? out : commonSuffix(suffixOut, out);
903  
      if (debug)
904  
        printState("processInOut(" + quote(in) + ", " + quote(out) + ")");
905  
    }
906  
    
907  
    void updateIn(String in) {
908  
      prefixIn = prefixIn == null ? in : commonPrefix(prefixIn, in);
909  
      suffixIn = suffixIn == null ? in : commonSuffix(suffixIn, in);
910  
      if (debug)
911  
        printState("updateIn(" + quote(in) + ")");
912  
    }
913  
914  
    public String processIn(Object _in) {
915  
      String in = (String) _in;
916  
      //System.out.println("[before last info] " + quote(prefixIn) + " " + quote(suffixIn) + " " + quote(prefixOut) + " " + quote(suffixOut));
917  
      //System.out.println("[last info] " + quote(in));
918  
      
919  
      // use latest information
920  
      String p = prefixIn, s = suffixIn;
921  
      updateIn(in);
922  
      prefixOut = prefixOut.substring(0, prefixOut.length()-(p.length()-prefixIn.length()));
923  
      suffixOut = suffixOut.substring(s.length()-suffixIn.length());
924  
      
925  
      //System.out.println("[after last info] " + quote(prefixIn) + " " + quote(suffixIn) + " " + quote(prefixOut) + " " + quote(suffixOut));
926  
      String core = in.substring(prefixIn.length(), in.length()-suffixIn.length());
927  
      return prefixOut + core + suffixOut;
928  
    }
929  
    
930  
    public void toJava(Code code) {
931  
      if (prefixIn.length() != 0 || suffixIn.length() != 0)
932  
        code.line(code.var + " = ((String) " + code.var + ").substring(" + prefixIn.length() + ", " + code.s() + ".length()-" + suffixIn.length() + ");");
933  
      if (prefixOut.length() != 0 || suffixOut.length() != 0)
934  
        code.line(code.var + " = " + quote(prefixOut) + " + " + code.var + " + " + quote(suffixOut) + ";");
935  
    }
936  
    
937  
    void printState(String text) {
938  
      System.out.println(text);
939  
      printVars();
940  
    }
941  
  }
942  
  
943  
  // for "find" tasks (e.g. "abcde" to "[[abc]]de")
944  
  static class LInputPattern extends LearnerImpl {
945  
    String regexp = "", findMarker1 = "[[", findMarker2 = "]]";
946  
    
947  
    public void processInOut(Object _in, Object _out) {
948  
      String in = (String) _in, out = (String) _out;
949  
      int i = out.indexOf(findMarker1), j = out.indexOf(findMarker2, i+1);
950  
      if (j < 0) return;
951  
      String s = out.substring(i+2, j);
952  
      regexp = s.replaceAll("\\d+", Matcher.quoteReplacement("\\d+"));
953  
      System.out.println("regexp: " + regexp);
954  
    }
955  
    
956  
    public String processIn(Object _in) {
957  
      String in = (String) _in;
958  
      if (regexp.length() == 0)
959  
        return in;
960  
      else
961  
        return in.replaceAll("(" + regexp + ")", findMarker1 + "$1" + findMarker2);
962  
    }
963  
    
964  
    public void toJava(Code code) {
965  
      code.line(code.var + " = ((String) " + code.var + ").replaceAll(" + quote("(" + regexp + ")") + ", \"[[$1]]\");");
966  
    }
967  
  }
968  
  
969  
  static class LFixed extends LearnerImpl {
970  
    static boolean debug;
971  
    Object value;
972  
    
973  
    public void processInOut(Object in, Object out) {
974  
      value = out;
975  
      if (debug)
976  
        printVars();
977  
    }
978  
    
979  
    public Object processIn(Object in) {
980  
      return value;
981  
    }
982  
    
983  
    public void toJava(Code code) {
984  
      code.line(code.var + " = " + quote((String) value) + ";");
985  
    }
986  
  }
987  
  
988  
  static void fail(String msg) {
989  
    throw new RuntimeException(msg);
990  
  }
991  
  
992  
  static void assertSameSize(List a, List b) {
993  
    if (a.size() != b.size())
994  
      fail("wrong list sizes");
995  
  }
996  
997  
  // process lists in parallel
998  
  // (in and out must be a list of same length)
999  
  static class LEach extends LearnerImpl {
1000  
    static boolean debug;
1001  
    Learner base;
1002  
    
1003  
    LEach(Learner base) {
1004  
      this.base = base;
1005  
    }
1006  
    
1007  
    public void processInOut(Object _in, Object _out) {
1008  
      List in = (List) _in, out = (List) _out;
1009  
      assertSameSize(in, out);
1010  
      for (int i = 0; i < in.size(); i++)
1011  
        base.processInOut(in.get(i), out.get(i));
1012  
      if (debug)
1013  
        printVars();
1014  
    }
1015  
    
1016  
    public Object processIn(Object _in) {
1017  
      List in = (List) _in;
1018  
      List out = new ArrayList();
1019  
      for (Object x : in)
1020  
        out.add(base.processIn(x));
1021  
      return out;
1022  
    }
1023  
    
1024  
    public void toJava(Code code) {
1025  
      code.line("List out = new ArrayList();");
1026  
      code.line("for (Object x : (List) in) {");
1027  
      code.indent();
1028  
      code.line("in = x;");
1029  
      base.toJava(code);
1030  
      code.line("out.add(in);");
1031  
      code.unindent();
1032  
      code.line("}");
1033  
      code.line("in = out;");
1034  
    }
1035  
  }
1036  
  
1037  
  static class LChange extends LearnerImpl {
1038  
    Function f;
1039  
    Learner base;
1040  
    
1041  
    LChange(Function f, Learner base) {
1042  
      this.f = f;
1043  
      this.base = base;
1044  
    }
1045  
    
1046  
    public void processInOut(Object in, Object out) {
1047  
      in = f.process(in);
1048  
      base.processInOut(in, out);
1049  
    }
1050  
    
1051  
    public Object processIn(Object in) {
1052  
      in = f.process(in);
1053  
      return base.processIn(in);
1054  
    }
1055  
    
1056  
    public void toJava(Code code) {
1057  
      f.toJava_process(code);
1058  
      base.toJava(code);
1059  
    }
1060  
  }
1061  
  
1062  
  static class LFindOutInIn extends LearnerImpl {
1063  
    static boolean debug;
1064  
    Learner base;
1065  
    String findMarker1 = "{{", findMarker2 = "}}";
1066  
    
1067  
    *(Learner *base) {}
1068  
    
1069  
    public void processInOut(Object _in, Object _out) {
1070  
      String in = (String) _in, out = (String) _out;
1071  
      if (out.length() == 0)
1072  
        out = in;
1073  
      else {
1074  
        int i = in.indexOf(out);
1075  
        if (i < 0) throw new RuntimeException("error");
1076  
        int j = i+out.length();
1077  
        out = in.substring(0, i) + findMarker1 + in.substring(i, j) + findMarker2 + in.substring(j);
1078  
        if (debug)
1079  
          System.out.println("LFindOutInIn: index=" + i);
1080  
      }
1081  
      
1082  
      base.processInOut(in, out);
1083  
      
1084  
      if (debug)
1085  
        System.out.println("LFindOutInIn: Base learned. " + base);
1086  
    }
1087  
    
1088  
    public Object processIn(Object _in) {
1089  
      if (debug)
1090  
        System.out.println("LFindOutInIn: processIn");
1091  
      String in = (String) _in;
1092  
      String out = (String) base.processIn(in);
1093  
      int i = out.indexOf(findMarker1), j = out.indexOf(findMarker2, i)-2;
1094  
      String result = i < 0 ? "" : in.substring(i, j);
1095  
      if (debug)
1096  
        System.out.println("LFindOutInIn: processIn " + i + " " + j + " " + quote(result));
1097  
      return result;
1098  
    }
1099  
    
1100  
    public void tryAgain() {
1101  
      base.tryAgain();
1102  
    }
1103  
  }
1104  
  
1105  
  static class LBoth extends LearnerImpl {
1106  
    ReversibleFunction f;
1107  
    Learner base;
1108  
    
1109  
    LBoth(ReversibleFunction f, Learner base) {
1110  
      this.f = f;
1111  
      this.base = base;
1112  
    }
1113  
    
1114  
    public void processInOut(Object in, Object out) {
1115  
      in = f.process(in);
1116  
      out = f.process(out);
1117  
      base.processInOut(in, out);
1118  
    }
1119  
    
1120  
    public Object processIn(Object in) {
1121  
      in = f.process(in);
1122  
      in = base.processIn(in);
1123  
      in = f.unprocess(in);
1124  
      return in;
1125  
    }
1126  
    
1127  
    public void toJava(Code code) {
1128  
      f.toJava_process(code);
1129  
      base.toJava(code);
1130  
      f.toJava_unprocess(code);
1131  
    }
1132  
  }
1133  
  
1134  
  static class RFJavaTok implements ReversibleFunction {
1135  
    public Object process(Object in) {
1136  
      return JavaTok.split((String) in);
1137  
    }
1138  
    
1139  
    public Object unprocess(Object in) {
1140  
      return JavaTok.join((List) in);
1141  
    }
1142  
    
1143  
    public void toJava_process(Code code) {
1144  
      code.translators("!636", "!class JavaTok");
1145  
      code.line(code.var + " = JavaTok.split((String) " + code.var + ");");
1146  
    }
1147  
    
1148  
    public void toJava_unprocess(Code code) {
1149  
      code.translators("!636", "!class JavaTok");
1150  
      code.line(code.var + " = JavaTok.join((List) " + code.var + ");");
1151  
    }
1152  
  }
1153  
  
1154  
  static class RFToLines implements ReversibleFunction {
1155  
    public Object process(Object in) {
1156  
      return toLines((String) in);
1157  
    }
1158  
    
1159  
    public Object unprocess(Object in) {
1160  
      return fromLines((List) in);
1161  
    }
1162  
    
1163  
    public void toJava_process(Code code) {
1164  
      code.translators("!636", "!standard functions");
1165  
      code.assign("toLines(" + code.s() + ");");
1166  
    }
1167  
    
1168  
    public void toJava_unprocess(Code code) {
1169  
      code.translators("!636", "!standard functions");
1170  
      code.assign("fromLines(" + code.list() + ");");
1171  
    }
1172  
  }
1173  
  
1174  
  // works on a token list - makes a list of only the string constants (unquoted)
1175  
  static class FStringsOnly implements Function {
1176  
    static boolean debug;
1177  
    
1178  
    public Object process(Object _in) {
1179  
      new List<String> tok;
1180  
      for (String s : (List<String>) _in) {
1181  
        boolean isString = s.startsWith("\"") || s.startsWith("[[");
1182  
        if (isString)
1183  
          tok.add(unquote(s));
1184  
        if (debug)
1185  
          System.out.println("FStringsOnly - isString: " + isString + " - " + s);
1186  
      }
1187  
      return tok;
1188  
    }
1189  
    
1190  
    public void toJava_process(Code code) {
1191  
      code.translators("!standard functions");
1192  
      code.line("List<String> tok = new ArrayList<String>();");
1193  
      code.line("for (String s : (List<String>) " + code.var + ")");
1194  
      code.line("  if (s.startsWith(\"\\\"\") || s.startsWith(\"[[\")) tok.add(unquote(s));");
1195  
      code.assign("tok");
1196  
    }
1197  
  }
1198  
  
1199  
  // works on a token list - makes a list of only the number constants
1200  
  static class FNumbersOnly implements Function {
1201  
    static boolean debug;
1202  
    
1203  
    public Object process(Object _in) {
1204  
      new List<String> tok;
1205  
      for (String s : (List<String>) _in) {
1206  
        boolean isNumber = s.length() != 0 && (Character.isDigit(s.charAt(0)) || (s.charAt(0) == '-' && s.length() > 1));
1207  
        if (isNumber)
1208  
          tok.add(s);
1209  
        if (debug)
1210  
          System.out.println("FNumbersOnly - isNumber: " + isNumber + " - " + s);
1211  
      }
1212  
      return tok;
1213  
    }
1214  
    
1215  
    public void toJava_process(Code code) {
1216  
      code.line("List<String> tok = new ArrayList<String>();");
1217  
      code.line("for (String s : (List<String>) " + code.var + ")");
1218  
      code.line("  if (s.length() != 0 && (Character.isDigit(s.charAt(0)) || (s.charAt(0) == '-' && s.length() > 1))) tok.add(s);");
1219  
      code.assign("tok");
1220  
    }
1221  
  }
1222  
  
1223  
  static class FLength implements Function {
1224  
    static boolean debug;
1225  
    
1226  
    public Object process(Object in) {
1227  
      Object result = String.valueOf(in instanceof List ? ((List) in).size() : ((String) in).length());
1228  
      if (debug)
1229  
        System.out.println("FLength: " + result);
1230  
      return result;
1231  
    }
1232  
    
1233  
    public void toJava_process(Code code) {
1234  
      code.assign("String.valueOf(" + code.var + " instanceof List ? " + code.list() + ".size() : " + code.s() + ".length())");
1235  
    }
1236  
  }
1237  
  
1238  
  static class LFixedFunction extends LearnerImpl {
1239  
    Function f;
1240  
    
1241  
    LFixedFunction(Function f) {
1242  
      this.f = f;
1243  
    }
1244  
    
1245  
    public void processInOut(Object in, Object out) {
1246  
    }
1247  
    
1248  
    public Object processIn(Object in) {
1249  
      return f.process(in);
1250  
    }
1251  
    
1252  
    public void toJava(Code code) {
1253  
      f.toJava_process(code);
1254  
    }
1255  
  }
1256  
  
1257  
  // trivial stuff like taking the one element out of a 1-element list
1258  
  static class LTrivial extends LearnerImpl {
1259  
    public void processInOut(Object in, Object out) {
1260  
    }
1261  
    
1262  
    public Object processIn(Object in) {
1263  
      return ((List) in).get(0);
1264  
    }
1265  
    
1266  
    public void toJava(Code code) {
1267  
      code.assign(code.list() + ".get(0)");
1268  
    }
1269  
  }
1270  
  
1271  
  // get element of a list at fixed index
1272  
  static class LGetListElement extends LearnerImpl {
1273  
    static boolean debug;
1274  
    int i;
1275  
    
1276  
    public void processInOut(Object _in, Object out) {
1277  
      List in = (List) _in;
1278  
      i = in.indexOf(out);
1279  
      if (debug)
1280  
        System.out.println("LGetListElement: " + i + " " + out);
1281  
    }
1282  
    
1283  
    public Object processIn(Object in) {
1284  
      return ((List) in).get(i);
1285  
    }
1286  
    
1287  
    public void toJava(Code code) {
1288  
      code.assign(code.list() + ".get(" + i + ")");
1289  
    }
1290  
  }
1291  
  
1292  
  // math operations
1293  
  static class LMath extends LearnerImpl {
1294  
    static boolean debug;
1295  
    String allOperations = "+ - * /";
1296  
    new (Tree)Set<String> possibleOperations;
1297  
    
1298  
    LMath() {
1299  
      possibleOperations.addAll(Arrays.asList(allOperations.split(" +")));
1300  
    }
1301  
    
1302  
    public void processInOut(Object _in, Object _out) {
1303  
      List in = (List) _in;
1304  
      String out = (String) _out;
1305  
      BigInteger[] inNumbers = getNumbers(in);
1306  
      BigInteger[] outNumbers = new BigInteger[] {getNumber(out)};
1307  
      findOperation(inNumbers, outNumbers);
1308  
      if (debug)
1309  
        System.out.println("Operations: " + possibleOperations);
1310  
    }
1311  
    
1312  
    public void findOperation(BigInteger[] in, BigInteger[] out) {
1313  
      filterOperations(in, out);
1314  
      if (possibleOperations.isEmpty())
1315  
        fail("tilt");
1316  
    }
1317  
      
1318  
    public void filterOperations(BigInteger[] in, BigInteger[] out) {
1319  
      for (Iterator<String> i = possibleOperations.iterator(); i.hasNext(); ) {
1320  
        String op = i.next();
1321  
        BigInteger[] out2 = doOperation(op, in);
1322  
        if (out2 == null || !arraysEqual(out, out2))
1323  
          i.remove(); // keep only matching operations
1324  
      }
1325  
    }
1326  
    
1327  
    public BigInteger[] doOperation(String op, BigInteger[] in) {
1328  
      op = op.intern();
1329  
      try {
1330  
        if (in.length == 2) {
1331  
          BigInteger a = in[0], b = in[1], x = null;
1332  
          if (op == "+")
1333  
            x = a.add(b);
1334  
          else if (op == "-")
1335  
            x = a.subtract(b);
1336  
          else if (op == "*")
1337  
            x = a.multiply(b);
1338  
          else if (op == "/")
1339  
            x = a.divide(b);
1340  
          return x != null ? new BigInteger[] {x} : null;
1341  
        }
1342  
        return null;
1343  
      } catch (Throwable e) {
1344  
        return null;
1345  
      }
1346  
    }
1347  
    
1348  
    public String processIn(Object _in) {
1349  
      List<String> in = (List<String>) _in;
1350  
      String op = possibleOperations.iterator().next();
1351  
      if (debug)
1352  
        System.out.println("op: " + op);
1353  
      BigInteger[] inNumbers = getNumbers(in);
1354  
      BigInteger[] outNumbers = doOperation(op, inNumbers);
1355  
      return outNumbers[0].toString();
1356  
    }
1357  
    
1358  
    String BI = BigInteger.class.getName();
1359  
    
1360  
    public void toJava(Code code) {
1361  
      String op = possibleOperations.iterator().next();
1362  
      String a = "new " + BI + "((String) " + code.list() + ".get(0))";
1363  
      String b = "new " + BI + "((String) " + code.list() + ".get(1))";
1364  
      if (op.equals("+"))
1365  
        code.assign(a + ".add(" + b + ").toString()");
1366  
      else
1367  
        todo();
1368  
    }
1369  
    
1370  
    static BigInteger[] getNumbers(List<String> in) {
1371  
      BigInteger[] big = new BigInteger[in.size()];
1372  
      for (int i = 0; i < in.size(); i++)
1373  
        big[i] = new BigInteger(in.get(i));
1374  
      return big;
1375  
    }
1376  
    
1377  
    static BigInteger getNumber(String s) {
1378  
      return new BigInteger(s);
1379  
    }
1380  
    
1381  
    static boolean arraysEqual(BigInteger[] a, BigInteger[] b) {
1382  
      if (a.length != b.length) return false;
1383  
      for (int i = 0; i < a.length; i++)
1384  
        if (!a[i].equals(b[i])) return false;
1385  
      return true;
1386  
    }
1387  
  }
1388  
  
1389  
  static class EscapeCase implements Function {
1390  
    static boolean debug;
1391  
    
1392  
    public Object process(Object _in) {
1393  
      if (debug)
1394  
        System.out.println("EscapeCase: " + _in);
1395  
      String in = (String) _in;
1396  
      return in.equals("case") ? "_case" : in;
1397  
    }
1398  
    
1399  
    public void toJava_process(Code code) {
1400  
      code.line("if (\"case\".equals(" + code.var + ")) " + code.var + " = " + quote("_case") + ";");
1401  
    }
1402  
  }
1403  
  
1404  
  static class LCharShift extends LearnerImpl {
1405  
    int shift;
1406  
    
1407  
    public void processInOut(Object _in, Object _out) {
1408  
      String in = (String) _in, out = (String) _out;
1409  
      shift = (int) out.charAt(0) - (int) in.charAt(0);
1410  
    }
1411  
    
1412  
    public Object processIn(Object _in) {
1413  
      String in = (String) _in;
1414  
      char[] c = new char[in.length()];
1415  
      for (int i = 0; i < c.length; i++)
1416  
        c[i] = (char) ((int) in.charAt(i) + shift);
1417  
      return new String(c);
1418  
    }
1419  
    
1420  
    public void toJava(Code code) {
1421  
      code.line("char[] c = new char[((String) " + code.var + ").length()];");
1422  
      code.line("for (int i = 0; i < c.length; i++)");
1423  
      code.line("  c[i] = (char) ((int) ((String) " + code.var + ").charAt(i)" + (shift < 0 ? "" + shift : "+" + shift) + ");");
1424  
      code.line(code.var + " = new String(c);");
1425  
    }
1426  
  }
1427  
  
1428  
  // applies base learner to first char of string
1429  
  // (or first element of list, TODO)
1430  
  static class LFirst extends LearnerImpl {
1431  
    Learner baseLearner;
1432  
    
1433  
    *(Learner baseLearner) {
1434  
      this.baseLearner = baseLearner;
1435  
    }
1436  
    
1437  
    public void processInOut(Object _in, Object _out) {
1438  
      String in = (String) _in, out = (String) _out;
1439  
      if (in.length() == 0)
1440  
        return;
1441  
      String firstIn = in.substring(0, 1), firstOut = out.substring(0, 1);
1442  
      baseLearner.processInOut(firstIn, firstOut);
1443  
    }
1444  
    
1445  
    public Object processIn(Object _in) {
1446  
      String in = (String) _in;
1447  
      if (in.length() == 0)
1448  
        return in;
1449  
      String firstIn = in.substring(0, 1);
1450  
      return baseLearner.processIn(firstIn) + in.substring(1);
1451  
    }
1452  
    
1453  
    public void toJava(Code code) {
1454  
      code.line("if (" + code.s() + ".length() != 0) {");
1455  
      code.indent();
1456  
      code.line("String rest = " + code.s() + ".substring(1);");
1457  
      code.line(code.var + " = " + code.s() + ".substring(0, 1);");
1458  
      baseLearner.toJava(code);
1459  
      code.line(code.var + " = " + code.s() + "+rest;");
1460  
      code.unindent();
1461  
      code.line("}");
1462  
    }
1463  
  }
1464  
  
1465  
  static Method findMainMethod(Class<?> theClass) {
1466  
    for (Method method : theClass.getMethods())
1467  
      if (method.getName().equals("main") && method.getParameterTypes().length == 1)
1468  
        return method;
1469  
    throw new RuntimeException("Method 'main' with 1 parameter not found in " + theClass.getName());
1470  
  }
1471  
  
1472  
  // compile JavaX source and load main class
1473  
  static Class<?> compileAndLoadMainClass(String src) tex {
1474  
    File srcDir = _x18.TempDirMaker_make();
1475  
    File classesDir = _x18.TempDirMaker_make();
1476  
    _x18.saveTextFile(new File(srcDir, "main.java").getPath(), src);
1477  
    new List<File> libraries;
1478  
    File transpiledDir = _x18.topLevelTranslate(srcDir, libraries);
1479  
    String javacOutput = _x18.compileJava(transpiledDir, libraries, classesDir);
1480  
    System.out.println(javacOutput);
1481  
    URL[] urls = {classesDir.toURI().toURL()};
1482  
    
1483  
    // make class loader
1484  
    URLClassLoader classLoader = new URLClassLoader(urls);
1485  
1486  
    // load main class
1487  
    Class<?> mainClass = classLoader.loadClass("main");
1488  
    return mainClass;
1489  
  }
1490  
      
1491  
  static Method compileJavaInToOut(Code code) {
1492  
    try {
1493  
      String java = code.buf.toString();
1494  
      String prelude = /*"import java.util.*;\n\n" +*/
1495  
        "public class main { public static Object main(Object in) throws Exception {\n";
1496  
      String postlude = "\nreturn in;\n}}";
1497  
      String src = code.getTranslators() + "\n" + prelude + java + postlude;
1498  
      Class<?> mainClass = compileAndLoadMainClass(src);
1499  
      return findMainMethod(mainClass);
1500  
    } catch (Exception e) {
1501  
      throw new RuntimeException(e);
1502  
    }
1503  
  }
1504  
  
1505  
  static Method findCalcMethod(Class<?> theClass) {
1506  
    for (Method method : theClass.getMethods())
1507  
      if (method.getName().equals("calc"))
1508  
        return method;
1509  
    throw new RuntimeException("Method 'calc' not found in " + theClass.getName());
1510  
  }
1511  
  
1512  
  // for simplejava stuff (execute tasks)
1513  
  static String execute(String src) {
1514  
    try {
1515  
      Class<?> mainClass = compileAndLoadMainClass(src);
1516  
      Method m = findCalcMethod(mainClass);
1517  
      return String.valueOf(m.invoke(null));
1518  
    } catch (Exception e) {
1519  
      throw new RuntimeException(e);
1520  
    }
1521  
  }
1522  
  
1523  
  static void testJava(Case case, Code code) {
1524  
    try {
1525  
      Method m = compileJavaInToOut(code);
1526  
      
1527  
      for (String[] e : case.fullExamples) {
1528  
        String out = (String) m.invoke(null, e[0]);
1529  
        
1530  
        if (!e[1].equals(out)) {
1531  
          throw new RuntimeException("[fail] Java code on " + quote(e[0]) + " - got: " + quote(out) + " rather than: " + quote(e[1]));
1532  
        }
1533  
      }
1534  
      
1535  
      System.out.println("\nGOOD JAVA.");
1536  
      case.goodJava = true;
1537  
    } catch (Throwable e) {
1538  
      if (showFails)
1539  
        e.printStackTrace();
1540  
      System.out.println("\nBAD JAVA.");
1541  
    }
1542  
  }
1543  
  
1544  
  static void todo() {
1545  
    fail("todo");
1546  
  }
1547  
  
1548  
  static class LSwitch extends LearnerImpl {
1549  
    Case case;
1550  
    Learner switcher;
1551  
    
1552  
    *(Case case, Learner switcher) {
1553  
      this.case = case;
1554  
      this.switcher = switcher;
1555  
    }
1556  
    
1557  
    public void processInOut(Object in, Object out) {
1558  
    }
1559  
   
1560  
    public Object processIn(Object in) {
1561  
      int i = Integer.parseInt((String) switcher.processIn(in));
1562  
      return case.combined.get(i-1).winner.processIn(in);
1563  
    }
1564  
   
1565  
    public void toJava(Code code) {
1566  
      todo();
1567  
    }
1568  
  }
1569  
 
1570  
  static class LTryPrevious extends LearnerImpl {
1571  
    new List<Case> candidates;
1572  
    
1573  
    *() {
1574  
      for (int i = caseIdx-1; i >= 0; i--)
1575  
        candidates.add(cases.get(i));
1576  
    }
1577  
1578  
    public void processInOut(Object _in, Object _out) {
1579  
      String in = (String) _in, out = (String) _out;
1580  
      for (ListIterator<Case> i = candidates.listIterator(); i.hasNext(); ) {
1581  
        Case case = i.next();
1582  
        if (case.winner == null || !validate(new String[] {in, out}, case.winner))
1583  
          i.remove();
1584  
      }
1585  
      if (candidates.isEmpty())
1586  
        fail("no previous solution found");
1587  
    }
1588  
  
1589  
    public Object processIn(Object in) {
1590  
      return candidates.get(0).winner.processIn(in);
1591  
    }
1592  
  
1593  
    public void toJava(Code code) {
1594  
      candidates.get(0).winner.toJava(code);
1595  
    }
1596  
  }
1597  
  
1598  
  static class LMulti extends LearnerImpl {
1599  
    static boolean debug;
1600  
    new List<Learner> candidates;
1601  
    
1602  
    *(Learner... learners) {
1603  
      for (Learner l : learners)
1604  
        candidates.add(l);
1605  
    }
1606  
    
1607  
    *(L<Learner> learners) {
1608  
      for (Learner l : learners)
1609  
        candidates.add(l);
1610  
    }
1611  
    
1612  
    public void processInOut(Object in, Object out) {
1613  
      if (debug)
1614  
        System.err.println("LMulti candidates: " + candidates.size());
1615  
      for (ListIterator<Learner> i = candidates.listIterator(); i.hasNext(); ) {
1616  
        Learner l = i.next();
1617  
        try {
1618  
          l.processInOut(in, out);
1619  
        } catch (Throwable e) {
1620  
          if (debug) {
1621  
            e.printStackTrace();
1622  
            System.err.println("Removing candidate: " + structure(l));
1623  
          }
1624  
          silentException(e);
1625  
          i.remove();
1626  
        }
1627  
      }
1628  
      if (debug)
1629  
        System.err.println("LMulti candidates now: " + candidates.size());
1630  
      if (candidates.isEmpty())
1631  
        fail("no candidates left");
1632  
    }
1633  
    
1634  
    public Object processIn(Object in) {
1635  
      while (true) { // fails or returns eventually
1636  
        Learner l = candidates.get(0);
1637  
        if (debug)
1638  
          System.err.println("Using candidate: " + structure(l) + ", " + candidates.size() + " left");
1639  
        try {
1640  
          return l.processIn(in);
1641  
        } catch (Throwable e) {
1642  
          if (debug) {
1643  
            e.printStackTrace();
1644  
            System.err.println("Removing candidate: " + structure(l));
1645  
          }
1646  
          silentException(e);
1647  
          candidates.remove(0);
1648  
        }
1649  
      }
1650  
    }
1651  
    
1652  
    public void tryAgain() {
1653  
      candidates.remove(0);
1654  
    }
1655  
    
1656  
    public void toJava(Code code) {
1657  
      candidates.get(0).toJava(code);
1658  
    }
1659  
  }
1660  
  
1661  
  static String structure(Object o) {
1662  
    String name = o.getClass().getName();
1663  
    
1664  
    new StringBuilder buf;
1665  
    
1666  
    if (o instanceof Collection) {
1667  
      for (Object x : (Collection) o) {
1668  
        if (!buf.isEmpty()) buf.append(", ");
1669  
        buf.append(structure(x));
1670  
      }
1671  
      return "{" + buf + "}";
1672  
    }
1673  
    
1674  
    // Need more cases? This should cover all library classes...
1675  
    if (name.startsWith("java.") || name.startsWith("javax."))
1676  
      return String.valueOf(o);
1677  
      
1678  
    String shortName = o.getClass().getName().replaceAll("^main\\$", "");
1679  
1680  
    // TODO: go to superclasses too
1681  
    Field[] fields = o.getClass().getDeclaredFields();
1682  
    for (Field field : fields) {
1683  
      if ((field.getModifiers() & Modifier.STATIC) != 0)
1684  
        continue;
1685  
      Object value;
1686  
      try {
1687  
        value = field.get(o);
1688  
      } catch (Exception e) {
1689  
        value = "?";
1690  
      }
1691  
      
1692  
      String fieldName = field.getName();
1693  
      
1694  
      // special case for LMulti - show only first (current) candidate
1695  
      if (shortName.equals("LMulti") && field.getName().equals("candidates")) {
1696  
        fieldName = "candidate";
1697  
        value = ((List) value).isEmpty() ? value : ((List) value).get(0);
1698  
      }
1699  
        
1700  
      if (!buf.isEmpty()) buf.append(", ");
1701  
      buf.append(fieldName + "=" + structure(value));
1702  
    }
1703  
    String s = shortName;
1704  
    if (!buf.isEmpty())
1705  
      s += "(" + buf + ")";
1706  
    return s;
1707  
  }
1708  
  
1709  
  static class FIsString implements Function {
1710  
    static boolean debug;
1711  
    
1712  
    public Object process(Object _in) {
1713  
      String in = (String) _in;
1714  
      return in.startsWith("\"") || in.startsWith("[[") ? "1" : "0";
1715  
    }
1716  
    
1717  
    public void toJava_process(Code code) {
1718  
      code.assign(code.s() + ".startsWith(\"\\\"\") || " + code.s() + ".startsWith(\"[[\") ? \"1\" : \"0\"");
1719  
    }
1720  
  }
1721  
  
1722  
  static class FCommonPrefix implements Function {
1723  
    static boolean debug;
1724  
1725  
    public Object process(Object _in) {
1726  
      String in = (String) _in, prefix = null;
1727  
      for (String line : toLines(in))
1728  
        if (line.length() != 0) {
1729  
          prefix = prefix == null ? line : commonPrefix(prefix, line);
1730  
          if (debug)
1731  
            System.out.println("FCommonPrefix: line=" + quote(line) + ", prefix=" + quote(prefix));
1732  
        }
1733  
      return prefix;
1734  
    }
1735  
    
1736  
    public void toJava_process(Code code) {
1737  
      todo();
1738  
    }
1739  
  }
1740  
  
1741  
  static class FCommonSuffix implements Function {
1742  
    static boolean debug;
1743  
1744  
    public Object process(Object _in) {
1745  
      String in = (String) _in, suffix = null;
1746  
      for (String line : toLines(in))
1747  
        if (line.length() != 0) {
1748  
          suffix = suffix == null ? line : commonSuffix(suffix, line);
1749  
          if (debug)
1750  
            System.out.println("FCommonSuffix: line=" + quote(line) + ", suffix=" + quote(suffix));
1751  
        }
1752  
      return suffix;
1753  
    }
1754  
    
1755  
    public void toJava_process(Code code) {
1756  
      todo();
1757  
    }
1758  
  }
1759  
  
1760  
  /*static class Pair {
1761  
    Object a, b;
1762  
    
1763  
    public boolean equals(Object o) {
1764  
      return o instanceof Pair && a.equals(((Pair) o).a) && b.equals((Pair) o).b);
1765  
    }
1766  
    
1767  
    public int hashCode() {
1768  
      return a.hashCode()+b.hashCode()*2;
1769  
    }
1770  
  }*/
1771  
  
1772  
  static class Matrix {
1773  
    new HashMap<Object, Map> dataByCol;
1774  
    
1775  
    void put(Object col, Object row, Object value) {
1776  
      //data.put(new Pair(col, row), value);
1777  
      getCol(col).put(row, value);
1778  
    }
1779  
    
1780  
    Map getCol(Object col) {
1781  
      Map map = dataByCol.get(col);
1782  
      if (map == null)
1783  
        dataByCol.put(col, map = new HashMap());
1784  
      return map;
1785  
    }
1786  
    
1787  
    Object get(Object col, Object row) {
1788  
      //return data.get(new Pair(col, row));
1789  
      return getCol(col).get(row);
1790  
    }
1791  
    
1792  
    Set cols() {
1793  
      return dataByCol.keySet();
1794  
    }
1795  
    
1796  
    Set rowsFor(Object col) {
1797  
      return getCol(col).keySet();
1798  
    }
1799  
  }
1800  
  
1801  
  static class LDistinguishList extends LearnerImpl {
1802  
    static boolean debug;
1803  
    Function helper;
1804  
    int idx;
1805  
    new Matrix matrix;
1806  
1807  
    *(Function helper) {
1808  
      this.helper = helper;
1809  
    }
1810  
    
1811  
    public void processInOut(Object _in, Object out) {
1812  
      List in = (List) _in;
1813  
      for (int i = 0; i < in.size(); i++) {
1814  
        Object y = helper.process(in.get(i));
1815  
        matrix.put(i, y, out);
1816  
      }
1817  
    }
1818  
    
1819  
    public Object processIn(Object _in) {
1820  
      // find idx
1821  
      
1822  
      for (Object i : matrix.cols()) {
1823  
        Collection ys = matrix.rowsFor(i);
1824  
        if (ys.size() > 1) {
1825  
          idx = (Integer) i;
1826  
          break;
1827  
        }
1828  
      }
1829  
      
1830  
      List in = (List) _in;
1831  
      Object y = helper.process(in.get(idx));
1832  
      return matrix.get(idx, y);
1833  
    }
1834  
    
1835  
    public void toJava(Code code) {
1836  
      List ys = new ArrayList(matrix.rowsFor(idx));
1837  
      //String v = code.var;
1838  
      //code.newVar();
1839  
      //String vy = code.var;
1840  
      //code.oldVar();
1841  
      code.assign(code.list() + ".get(" + idx + ")");
1842  
      helper.toJava_process(code);
1843  
      
1844  
      for (int i = 0; i < ys.size(); i++) {
1845  
        Object y = ys.get(i);
1846  
        if (i < ys.size())
1847  
          code.line((i == 0 ? "" : "else ") + "if (" + quote((String) y) + ".equals(" + code.var + "))");
1848  
        else
1849  
          code.line("else");
1850  
        code.line("  " + code.var + " = " + quote((String) matrix.get(idx, y)) + ";");
1851  
      }
1852  
    }
1853  
  }
1854  
  
1855  
  static class RunnersUp {
1856  
    String expected;
1857  
    int bestScore = -1;
1858  
    String bestResult;
1859  
    Learner winner;
1860  
    
1861  
    void add(String expected, String result, int score, Learner learner) {
1862  
      if (!expected.equals(this.expected) || bestScore == -1 || score < bestScore) {
1863  
        bestScore = score;
1864  
        bestResult = result;
1865  
        winner = learner;
1866  
      }
1867  
      this.expected = expected;
1868  
    }
1869  
  }
1870  
  
1871  
  static List<Case> casesSortedByID() {
1872  
    new (Tree)Map<Long, Case> map;
1873  
    new List<Case> rest;
1874  
    for (Case c : cases)
1875  
      if (isSnippetID(c.id))
1876  
        map.put(parseSnippetID(c.id), c);
1877  
      else
1878  
        rest.add(c);
1879  
    List<Case> list = new ArrayList<Case>(map.values());
1880  
    list.addAll(rest);
1881  
    return list;
1882  
  }
1883  
  
1884  
  !include #1000388 // leven (Levenshtein distance function)
1885  
  
1886  
  !include #1000382 // Box learners
1887  
  !include #1000387 // Empty box learner
1888  
  
1889  
  // for "find" tasks (e.g. "abcde" to "[[abc]]de")
1890  
  static class LFixedSubstring extends LearnerImpl {
1891  
    static boolean debug;
1892  
    String findMarker1 = "{{", findMarker2 = "}}";
1893  
    int i, j;
1894  
    
1895  
    public void processInOut(Object _in, Object _out) {
1896  
      String in = (String) _in, out = (String) _out;
1897  
      i = out.indexOf(findMarker1);
1898  
      j = out.indexOf(findMarker2, i)-2;
1899  
      if (debug && j >= 0) {
1900  
        boolean correct = in.substring(i, j).equals(out.substring(i+2, j+2));
1901  
        System.out.println("LFixedSubstring: i, j = " + i + ", " + j + " " + correct + " " + quote(in.substring(i, j)));
1902  
      }
1903  
    }
1904  
    
1905  
    public String processIn(Object _in) {
1906  
      String in = (String) _in;
1907  
      return in.substring(0, i) + findMarker1 + in.substring(i, j) + findMarker2 + in.substring(j);
1908  
    }
1909  
  }
1910  
1911  
  static void print(Object o) {
1912  
    System.out.println(o);
1913  
  }
1914  
}

Author comment

Began life as a copy of #695

-notestjava now default
Switched to Android-modified version of JavaX 18

download  show line numbers  debug dex  old transpilations   

Travelled to 16 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, hxnwyiuffukg, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, teubizvjbppd, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #704
Snippet name: IOIOI Processor (v11)
Eternal ID of this version: #704/1
Text MD5: d7dfe400f7f0b579f60a957c73626b34
Transpilation MD5: 8b80f3260103a02776f6e6f3e9711084
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-20 15:44:46
Source code size: 58894 bytes / 1914 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 695 / 1078
Referenced in: [show references]