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

1945
LINES

< > BotCompany Repo | #716 // IOIOI Processor (v12, "descent of choices")

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

Transpiled version (5521L) is out of date.

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

Author comment

Began life as a copy of #704

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #716
Snippet name: IOIOI Processor (v12, "descent of choices")
Eternal ID of this version: #716/1
Text MD5: 2649dfe53d86c7718568c4e4c9dcac70
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-09 02:39:39
Source code size: 59497 bytes / 1945 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 507 / 553
Referenced in: [show references]