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

2205
LINES

< > BotCompany Repo | #720 // IOIOI Processor (v14, changing examples to Object)

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

Libraryless. Click here for Pure Java version (6206L/41K/120K).

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

Author comment

Began life as a copy of #717

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #720
Snippet name: IOIOI Processor (v14, changing examples to Object)
Eternal ID of this version: #720/1
Text MD5: 698b8498567ddab77560c6689025a441
Transpilation MD5: 79934a4137434dd5fd2bdfcc11dcf435
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-09 18:05:49
Source code size: 67457 bytes / 2205 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 833 / 901
Referenced in: [show references]