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 |
|
11 | import java.lang.reflect.*;
|
12 | import java.math.*; // BigInteger
|
13 |
|
14 | !include #2000470 // class _x16
|
15 |
|
16 | interface Function {
|
17 | public Object process(Object in);
|
18 | public void toJava_process(Code code);
|
19 | }
|
20 |
|
21 | interface ReversibleFunction extends Function {
|
22 | public Object unprocess(Object in);
|
23 | public void toJava_unprocess(Code code);
|
24 | }
|
25 |
|
26 | // generic learner (works on objects)
|
27 | interface Learner {
|
28 | public void processInOut(Object in, Object out);
|
29 | public Object processIn(Object in);
|
30 | public void toJava(Code code);
|
31 | }
|
32 |
|
33 | interface Retry {} // marker interface for learners that want to retry
|
34 |
|
35 | abstract class Base {
|
36 | void printVars() {
|
37 | new StringBuilder buf;
|
38 | Field[] fields = getClass().getDeclaredFields();
|
39 | for (Field field : fields) {
|
40 | if ((field.getModifiers() & Modifier.STATIC) != 0)
|
41 | continue;
|
42 | Object value;
|
43 | try {
|
44 | value = field.get(this);
|
45 | } catch (Exception e) {
|
46 | value = "?";
|
47 | }
|
48 |
|
49 | if (!buf.isEmpty()) buf.append(", ");
|
50 | buf.append(field.getName() + "=" + value);
|
51 | }
|
52 | System.out.println(buf.toString());
|
53 | }
|
54 | }
|
55 |
|
56 | abstract class LearnerImpl extends Base implements Learner {
|
57 | }
|
58 |
|
59 | class Code {
|
60 | new StringBuilder buf;
|
61 | String var = "in";
|
62 | String indent = "";
|
63 | new List<String> translators;
|
64 | new List<String> varStack;
|
65 | int varCounter;
|
66 |
|
67 | Code() {
|
68 | translators.add("!636");
|
69 | }
|
70 |
|
71 | void line(String line) {
|
72 | buf.append(indent).append(line).append('\n');
|
73 | }
|
74 |
|
75 | void indent() {
|
76 | indent += " ";
|
77 | }
|
78 |
|
79 | void unindent() {
|
80 | indent = indent.substring(0, indent.length()-2);
|
81 | }
|
82 |
|
83 | void translators(String... ids) {
|
84 | for (String id : ids)
|
85 | if (! translators.contains(id)) // space is needed otherwise translator 636 is fooled :)
|
86 | translators.add(id);
|
87 | }
|
88 |
|
89 | String getTranslators() {
|
90 | // TODO: We should really fix the "standard functions" translator
|
91 | // to properly find the main class.
|
92 | //
|
93 | // As a hack, we move it upwards (before classes adding)
|
94 | int i = translators.indexOf("!standard functions");
|
95 | if (i >= 0) {
|
96 | translators.remove(i);
|
97 | translators.add(0, "!standard functions");
|
98 | }
|
99 |
|
100 | return main.fromLines(translators);
|
101 | }
|
102 |
|
103 | String s() {
|
104 | return "((String) " + var + ")";
|
105 | }
|
106 |
|
107 | String list() {
|
108 | return "((List) " + var + ")";
|
109 | }
|
110 |
|
111 | void assign(String exp) {
|
112 | line(var + " = " + exp + ";");
|
113 | }
|
114 |
|
115 | void newVar() {
|
116 | varStack.add(var);
|
117 | var = "_v" + (++varCounter);
|
118 | line("Object " + var + ";");
|
119 | }
|
120 |
|
121 | void oldVar() {
|
122 | var = varStack.get(varStack.size()-1);
|
123 | varStack.remove(varStack.size()-1);
|
124 | }
|
125 | }
|
126 |
|
127 | main {
|
128 | static new List<Case> cases;
|
129 | static new HashMap<String, Case> casesByID;
|
130 | static boolean testJava = true, showFails;
|
131 | static new (Hash)Set<String> parseErrors;
|
132 | static int caseIdx;
|
133 |
|
134 | psvm {
|
135 | new List<String> snippetIDs;
|
136 | new List<String> inputs;
|
137 |
|
138 | for (int i = 0; i < args.length; i++) {
|
139 | String arg = args[i];
|
140 | if (arg.equals("debug"))
|
141 | debugOn(args[++i]);
|
142 | else if (arg.equals("in"))
|
143 | inputs.add(args[++i]);
|
144 | else if (arg.equals("-notestjava"))
|
145 | testJava = false;
|
146 | else if (arg.equals("-testjava"))
|
147 | testJava = true;
|
148 | else if (arg.equals("-showfails"))
|
149 | showFails = true;
|
150 | else if (isSnippetID(arg))
|
151 | snippetIDs.add(arg);
|
152 | else
|
153 | System.err.println("Unknown argument: " + arg + ", ignoring");
|
154 | }
|
155 |
|
156 | if (snippetIDs.isEmpty())
|
157 | parse(null);
|
158 |
|
159 | for (String snippetID : snippetIDs)
|
160 | try {
|
161 | Case case = parse(snippetID);
|
162 | case.halfExamples.addAll(inputs);
|
163 | } catch (Throwable e) {
|
164 | e.printStackTrace();
|
165 | parseErrors.add(snippetID);
|
166 | }
|
167 |
|
168 | int solved = 0, n = cases.size(), goodJava = 0;
|
169 | for (caseIdx = 0; caseIdx < n; caseIdx++) {
|
170 | Case case = cases.get(caseIdx);
|
171 | try {
|
172 | calculate(case);
|
173 | } catch (Throwable e) {
|
174 | e.printStackTrace();
|
175 | }
|
176 | if (case.winner != null)
|
177 | ++solved;
|
178 | if (case.goodJava)
|
179 | ++goodJava;
|
180 | System.out.println((caseIdx+1) + " case(s) processed, " + solved + " solved.");
|
181 | if (testJava && goodJava < solved)
|
182 | System.out.println((solved-goodJava) + " case(s) with BAD JAVA.");
|
183 | }
|
184 |
|
185 | print ""
|
186 | print "----"
|
187 |
|
188 | boolean allSolved = solved == n;
|
189 | if (solved != 0) {
|
190 | System.out.println();
|
191 | System.out.print("Solved: ");
|
192 | for (Case case : cases)
|
193 | if (case.winner != null)
|
194 | System.out.print(case.id + " ");
|
195 | System.out.println();
|
196 | }
|
197 | if (testJava && solved > goodJava) {
|
198 | System.out.println();
|
199 | System.out.print("Bad Java: ");
|
200 | for (Case case : cases)
|
201 | if (case.winner != null && !case.goodJava)
|
202 | System.out.print(case.id + " ");
|
203 | System.out.println();
|
204 | }
|
205 | if (!allSolved) {
|
206 | System.out.println();
|
207 | System.out.print("Unsolved: ");
|
208 | for (Case case : cases)
|
209 | if (case.winner == null)
|
210 | System.out.print(case.id + " ");
|
211 | System.out.println();
|
212 | }
|
213 | if (!parseErrors.isEmpty()) {
|
214 | System.out.print("\nParse errors: ");
|
215 | for (String id : parseErrors)
|
216 | System.out.print(id + " ");
|
217 | System.out.println();
|
218 | }
|
219 | System.out.println();
|
220 | if (allSolved && testJava && goodJava < solved)
|
221 | System.out.println("All solved (" + solved + "), but some BAD JAVA.");
|
222 | else {
|
223 | System.out.println(allSolved ? "ALL SOLVED (" + solved + ")" : "Solved " + solved + " out of " + n + ".");
|
224 | if (testJava)
|
225 | if (goodJava == solved)
|
226 | System.out.println("All Java code OK" + (allSolved ? "" : " (for solved cases)") + ".");
|
227 | else
|
228 | System.out.println("Some bad Java.");
|
229 | else
|
230 | System.out.println("Java not tested.");
|
231 | }
|
232 | print ""
|
233 | }
|
234 |
|
235 | static class Case {
|
236 | String id;
|
237 | new List<String[]> fullExamples;
|
238 | new List<String> halfExamples;
|
239 | List<String[]> examples1, examples2;
|
240 | Learner winner;
|
241 | boolean goodJava;
|
242 | List<Case> combined;
|
243 | int splitPoint = -1;
|
244 |
|
245 | void split() {
|
246 | if (examples1 != null)
|
247 | return; // already done
|
248 | if (fullExamples.size() < 2)
|
249 | throw new RuntimeException("Too few examples (" + fullExamples.size() + ")");
|
250 | if (splitPoint < 0)
|
251 | splitPoint = fullExamples.size()-1;
|
252 | System.out.println("Full examples: " + fullExamples.size() + ", splitPoint: " + splitPoint + ", half examples: " + halfExamples.size());
|
253 | examples1 = fullExamples.subList(0, splitPoint);
|
254 | examples2 = fullExamples.subList(splitPoint, fullExamples.size());
|
255 | }
|
256 |
|
257 | void add(Case case) {
|
258 | combined.add(case);
|
259 | fullExamples.addAll(case.fullExamples);
|
260 | halfExamples.addAll(case.halfExamples);
|
261 | }
|
262 | }
|
263 |
|
264 | static Case parse(String arg) tex {
|
265 | new Case case;
|
266 | String text;
|
267 | if (arg != null) {
|
268 | if (casesByID.containsKey(arg))
|
269 | return casesByID.get(arg);
|
270 |
|
271 | if (arg.startsWith("Combine")) {
|
272 | case.id = "Combine";
|
273 | case.combined = new ArrayList<Case>();
|
274 | List<String> tok = JavaTok.split(arg);
|
275 | new List<String> ids;
|
276 | for (int i = 5; i < tok.size(); i += 6) { // skip # and "and"
|
277 | Case case2 = parse("#" + tok.get(i));
|
278 | case.id += " #" + tok.get(i);
|
279 | cases.remove(case2);
|
280 | case.add(case2);
|
281 | }
|
282 | addCase(case);
|
283 | return case;
|
284 | } else {
|
285 | case.id = arg;
|
286 | text = loadSnippet(arg);
|
287 | }
|
288 | } else {
|
289 | case.id = "input.txt";
|
290 | text = loadTextFile("input/input.txt", null);
|
291 | if (text == null) {
|
292 | //case.id = "#2000455"; // example input
|
293 | case.id = "#681"; // a collection of "all cases"!
|
294 | text = loadSnippet(case.id);
|
295 | }
|
296 | }
|
297 |
|
298 | // it's a collection of cases!
|
299 | if (text.trim().startsWith("#") || text.trim().startsWith("Combine")) {
|
300 | for (String line : toLines(text))
|
301 | parse(line);
|
302 | return null;
|
303 | }
|
304 |
|
305 | // it's a "Continue:" task - transform to I/O format
|
306 | if (text.trim().startsWith("Continue:")) {
|
307 | List<String> lines = toLines(text);
|
308 | new StringBuilder buf;
|
309 | for (int i = 1; i < lines.size(); i++) {
|
310 | buf.append("In: " + quote("" + i) + "\n");
|
311 | buf.append("Out: " + quote(lines.get(i)) + "\n");
|
312 | }
|
313 | int numAsking = 3;
|
314 | for (int i = lines.size(); i < lines.size()+numAsking; i++)
|
315 | buf.append("In: " + quote("" + i) + "\n");
|
316 | text = buf.toString();
|
317 | }
|
318 |
|
319 | // it's a "Execute." task - run Java(X) and transform to I/O format
|
320 | if (text.trim().startsWith("Execute.")) {
|
321 | List<String> tok = JavaTok.split(text);
|
322 | new StringBuilder buf;
|
323 | for (int i = 5; i < tok.size(); i += 2) {
|
324 | if (tok.get(i).equals("-") && tok.get(i+2).equals("-")) {
|
325 | i += 2;
|
326 | buf.append("--\n");
|
327 | } else {
|
328 | String code = unquote(tok.get(i));
|
329 | String result = execute("!636\n" + code);
|
330 | buf.append("In: " + quote(code) + "\n");
|
331 | buf.append("Out: " + quote(result) + "\n");
|
332 | }
|
333 | }
|
334 | text = buf.toString();
|
335 | }
|
336 |
|
337 | System.out.println(text);
|
338 | String in = null, out = null;
|
339 |
|
340 | List<String> tok = JavaTok.split(text);
|
341 | for (int i = 1; i < tok.size(); i += 2) {
|
342 | String t = tok.get(i), t2 = i+2 < tok.size() ? tok.get(i+2) : "";
|
343 | if (t.equals("-") && t2.equals("-")) {
|
344 | i += 2;
|
345 | case.splitPoint = case.fullExamples.size();
|
346 | } else if (t.toUpperCase().startsWith("I") && t2.equals(":")) { // "In: " or "I: "
|
347 | if (in != null)
|
348 | case.halfExamples.add(in);
|
349 | i += 4;
|
350 | int j = findNextLine(tok, i);
|
351 | in = unquote(JavaTok.join(tok.subList(i, j-1)));
|
352 | i = j-2;
|
353 | out = null;
|
354 | } else if (t.toUpperCase().startsWith("O") && t2.equals(":")) { // "Out: " or "O: "
|
355 | i += 4;
|
356 | int j = findNextLine(tok, i);
|
357 | out = unquote(JavaTok.join(tok.subList(i, j-1)));
|
358 | i = j-2;
|
359 | System.out.println(quote(in) + " => " + quote(out));
|
360 | case.fullExamples.add(new String[] {in, out});
|
361 | in = out = null;
|
362 | } else {
|
363 | int j = findNextLine(tok, i);
|
364 | String line = JavaTok.join(tok.subList(i, j-1));
|
365 | i = j-2;
|
366 | System.out.println("-- Ignoring line: " + line);
|
367 | }
|
368 | }
|
369 |
|
370 | if (in != null)
|
371 | case.halfExamples.add(in);
|
372 | addCase(case);
|
373 | return case;
|
374 | }
|
375 |
|
376 | // i is a code-token (odd index)
|
377 | // return value is also a code token, or end of list
|
378 | static int findNextLine(List<String> tok, int i) {
|
379 | while (i < tok.size() && tok.get(i+1).indexOf('\n') < 0)
|
380 | i += 2;
|
381 | return i+2;
|
382 | }
|
383 |
|
384 | static void addCase(Case case) {
|
385 | cases.add(case);
|
386 | casesByID.put(case.id, case);
|
387 | }
|
388 |
|
389 | static void calculate(Case case) tex {
|
390 | System.out.println("\n== CASE " + case.id + " ==");
|
391 |
|
392 | case.split();
|
393 | Learner learner = findOKLearner(case);
|
394 | if (learner == null)
|
395 | print "\nProblem not solved"
|
396 | else {
|
397 | print "\nSolved!"
|
398 | case.winner = learner;
|
399 | new Code code;
|
400 | try {
|
401 | learner.toJava(code);
|
402 |
|
403 | if (testJava)
|
404 | testJava(case, code); // prints "GOOD JAVA" or "BAD JAVA"
|
405 | else
|
406 | print "Java:"
|
407 |
|
408 | System.out.println(indent(" ", code.getTranslators()));
|
409 | System.out.println(indent(" ", code.buf.toString()));
|
410 | } catch (Throwable e) {
|
411 | print "BAD JAVA"
|
412 | }
|
413 |
|
414 | for (String in : case.halfExamples) {
|
415 | Object out = learner.processIn(in);
|
416 | System.out.println(quote(in) + " =>! " + quote((String) out));
|
417 | }
|
418 | }
|
419 | }
|
420 |
|
421 | static Learner findOKLearner(Case case) tex {
|
422 | for (Learner learner : makeLearners()) try {
|
423 | if (learnerOK(learner, case))
|
424 | return learner;
|
425 | } catch (Throwable e) {
|
426 | if (showFails)
|
427 | e.printStackTrace();
|
428 | }
|
429 |
|
430 | if (case.combined != null) {
|
431 | Case switchCase = makeSwitchCase(case);
|
432 | calculate(switchCase);
|
433 | Learner learner = switchCase.winner;
|
434 | if (learner != null)
|
435 | return new LSwitch(case, learner);
|
436 | }
|
437 |
|
438 | return null;
|
439 | }
|
440 |
|
441 | static Case makeSwitchCase(Case case) {
|
442 | int i = 0;
|
443 | Case s = new Case();
|
444 | s.id = "Switch " + case.id;
|
445 | s.examples1 = new ArrayList<String[]>();
|
446 | s.examples2 = new ArrayList<String[]>();
|
447 | for (Case c : case.combined) {
|
448 | ++i;
|
449 | for (String[] e : c.examples1)
|
450 | s.examples1.add(new String[] {e[0], String.valueOf(i)});
|
451 | for (String[] e : c.examples2)
|
452 | s.examples2.add(new String[] {e[0], String.valueOf(i)});
|
453 | for (String[] e : c.fullExamples)
|
454 | s.fullExamples.add(new String[] {e[0], String.valueOf(i)});
|
455 | }
|
456 | return s;
|
457 | }
|
458 |
|
459 | static boolean learnerOK(Learner learner, Case case) {
|
460 | String[] _e = null;
|
461 | try {
|
462 | if (case.examples1 == null)
|
463 | fail("Case not calculated: " + case.id);
|
464 | for (String[] e : case.examples1) {
|
465 | _e = e;
|
466 | learner.processInOut(e[0], e[1]);
|
467 | }
|
468 |
|
469 | // full validation against all examples
|
470 | int retry = 0;
|
471 | retryLoop: while (true) {
|
472 | for (String[] e : case.fullExamples) {
|
473 | _e = e;
|
474 | String out = (String) learner.processIn(e[0]);
|
475 | if (!e[1].equals(out)) {
|
476 | if (showFails)
|
477 | System.out.println("[fail] " + structure(learner) + " on " + quote(e[0]) + " - got: " + quote(out) + " rather than: " + quote(e[1]));
|
478 | if (!(learner instanceof Retry))
|
479 | return false;
|
480 | else {
|
481 | ++retry;
|
482 | System.err.println("Retry " + retry);
|
483 | continue retryLoop;
|
484 | }
|
485 | }
|
486 | }
|
487 | return true; // all test examples passed
|
488 | }
|
489 | } catch (Throwable e) {
|
490 | if (showFails) {
|
491 | e.printStackTrace();
|
492 | System.err.println("[fail] " + learner + " on " + (_e == null ? "?" : quote(_e[0])) + " - " + e);
|
493 | }
|
494 | return false;
|
495 | }
|
496 | }
|
497 |
|
498 | static boolean validate(String[] example, Learner learner) {
|
499 | try {
|
500 | String out = (String) learner.processIn(example[0]);
|
501 | if (!example[1].equals(out)) {
|
502 | //System.out.println("[fail] " + learner + " on " + quote(e[0]) + " - got: " + quote(out) + " rather than: " + quote(e[1]));
|
503 | return false;
|
504 | }
|
505 | return true;
|
506 | } catch (Throwable e) {
|
507 | silentException(e);
|
508 | return false;
|
509 | }
|
510 | }
|
511 |
|
512 | static void silentException(Throwable e) {
|
513 | }
|
514 |
|
515 | /* XXX - important part */
|
516 | static Iterable<Learner> makeLearners() {
|
517 | new List<Learner> list;
|
518 | list.addAll(level1());
|
519 | list.add(new LBox(new LMulti(level1())));
|
520 | return list;
|
521 | }
|
522 |
|
523 | static List<Learner> level1() {
|
524 | new List<Learner> list;
|
525 | //list.add(new LId()); // subsumed by trivial case of PrefixSuffix
|
526 | list.add(new LPrefixSuffix());
|
527 | list.add(new LSplitInput(new LOutPattern()));
|
528 | list.add(new LInputPattern());
|
529 | list.add(new LFixed());
|
530 | list.add(new LBoth(new RFJavaTok(), new LEach(new LFixedFunction(new EscapeCase()))));
|
531 | list.add(new LCharShift());
|
532 | list.add(new LOutSuffix(new LFirst(new LCharShift())));
|
533 |
|
534 | list.add(new LChange(new RFJavaTok(), new LMulti(
|
535 | new LChange(new FStringsOnly(), new LGetListElement()),
|
536 | new LChange(new FNumbersOnly(), new LMath()))
|
537 | ));
|
538 |
|
539 | // TODO - for #1000378
|
540 | list.add(new LChange(new RFJavaTok(), new LDistinguishList(new FIsString())));
|
541 |
|
542 | // of no use now it seems
|
543 | // list.add(new LTryPrevious());
|
544 |
|
545 | return list;
|
546 | }
|
547 |
|
548 | public static String unquote(String s) {
|
549 | if (s.startsWith("[[") && s.endsWith("]]"))
|
550 | return s.substring(2, s.length()-2);
|
551 | else if (s.startsWith("\"") && s.endsWith("\"") && s.length() > 1)
|
552 | return s.substring(1, s.length()-1).replace("\\\"", "\"").replace("\\\\", "\\"); // SHOULD work...
|
553 | else
|
554 | return s; // return original
|
555 | }
|
556 |
|
557 | public static String quote(String s) {
|
558 | if (s == null) return "null";
|
559 | return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
|
560 | }
|
561 |
|
562 | static String indent(String indent, String s) {
|
563 | return indent + s.replace("\n", "\n" + indent);
|
564 | }
|
565 |
|
566 | static void debugOn(String name) {
|
567 | try {
|
568 | Class c = Class.forName("main$" + name);
|
569 | Field field;
|
570 | while (true)
|
571 | try {
|
572 | field = c.getDeclaredField("debug");
|
573 | break;
|
574 | } catch (NoSuchFieldException e) {
|
575 | c = c.getSuperclass();
|
576 | }
|
577 | field.setBoolean(null, true);
|
578 | } catch (Exception e) {
|
579 | e.printStackTrace();
|
580 | System.err.println("Cannot debug class " + name);
|
581 | }
|
582 | }
|
583 |
|
584 | // splits the input at some point, takes only one part
|
585 | static class LSplitInput implements Learner {
|
586 | int splitIdx = 1; // split after first character
|
587 | Learner baseLearner;
|
588 |
|
589 | LSplitInput(Learner baseLearner) {
|
590 | this.baseLearner = baseLearner;
|
591 | }
|
592 |
|
593 | public void processInOut(Object _in, Object _out) {
|
594 | String in = (String) _in, out = (String) _out;
|
595 | in = in.substring(splitIdx);
|
596 | baseLearner.processInOut(in, out);
|
597 | }
|
598 |
|
599 | public Object processIn(Object _in) {
|
600 | String in = (String) _in;
|
601 | in = in.substring(splitIdx);
|
602 | return baseLearner.processIn(in);
|
603 | }
|
604 |
|
605 | public void toJava(Code code) {
|
606 | if (splitIdx != 0)
|
607 | code.line(code.var + " = ((String) " + code.var + ").substring(" + splitIdx + ");");
|
608 | baseLearner.toJava(code);
|
609 | }
|
610 | }
|
611 |
|
612 | // removes common suffix from out, delegates to base learner
|
613 | static class LOutSuffix implements Learner {
|
614 | String suffixOut = "";
|
615 | Learner baseLearner;
|
616 |
|
617 | LOutSuffix(Learner baseLearner) {
|
618 | this.baseLearner = baseLearner;
|
619 | }
|
620 |
|
621 | public void processInOut(Object _in, Object _out) {
|
622 | String in = (String) _in, out = (String) _out;
|
623 | if (out.endsWith("!"))
|
624 | suffixOut = "!";
|
625 | if (out.endsWith(suffixOut))
|
626 | out = out.substring(0, out.length()-suffixOut.length());
|
627 |
|
628 | baseLearner.processInOut(in, out);
|
629 | }
|
630 |
|
631 | public Object processIn(Object _in) {
|
632 | String in = (String) _in;
|
633 | return baseLearner.processIn(in) + suffixOut;
|
634 | }
|
635 |
|
636 | public void toJava(Code code) {
|
637 | baseLearner.toJava(code);
|
638 | if (suffixOut.length() != 0)
|
639 | code.line(code.var + " = " + code.s() + "+" + quote(suffixOut) + ";");
|
640 | }
|
641 | }
|
642 |
|
643 | // if input appears in output in fixed pattern
|
644 | static class LOutPattern implements Learner {
|
645 | String pattern = "%!%";
|
646 |
|
647 | public void processInOut(Object _in, Object _out) {
|
648 | String in = (String) _in, out = (String) _out;
|
649 | pattern = out.replace(in, "%!%");
|
650 | }
|
651 |
|
652 | public String processIn(Object _in) {
|
653 | String in = (String) _in;
|
654 | return pattern.replace("%!%", in);
|
655 | }
|
656 |
|
657 | public void toJava(Code code) {
|
658 | code.line(code.var + " = " + quote(pattern) + ".replace(" + quote("%!%") + ", (String) " + code.var + ");");
|
659 | }
|
660 | }
|
661 |
|
662 | // learns to exchange common prefixes and suffixes
|
663 | static class LPrefixSuffix extends LearnerImpl {
|
664 | static boolean debug;
|
665 | String prefixIn, suffixIn, prefixOut, suffixOut;
|
666 |
|
667 | public void processInOut(Object _in, Object _out) {
|
668 | String in = (String) _in, out = (String) _out;
|
669 | updateIn(in);
|
670 | prefixOut = prefixOut == null ? out : commonPrefix(prefixOut, out);
|
671 | suffixOut = suffixOut == null ? out : commonSuffix(suffixOut, out);
|
672 | if (debug)
|
673 | printState("processInOut(" + quote(in) + ", " + quote(out) + ")");
|
674 | }
|
675 |
|
676 | void updateIn(String in) {
|
677 | prefixIn = prefixIn == null ? in : commonPrefix(prefixIn, in);
|
678 | suffixIn = suffixIn == null ? in : commonSuffix(suffixIn, in);
|
679 | if (debug)
|
680 | printState("updateIn(" + quote(in) + ")");
|
681 | }
|
682 |
|
683 | public String processIn(Object _in) {
|
684 | String in = (String) _in;
|
685 | //System.out.println("[before last info] " + quote(prefixIn) + " " + quote(suffixIn) + " " + quote(prefixOut) + " " + quote(suffixOut));
|
686 | //System.out.println("[last info] " + quote(in));
|
687 |
|
688 | // use latest information
|
689 | String p = prefixIn, s = suffixIn;
|
690 | updateIn(in);
|
691 | prefixOut = prefixOut.substring(0, prefixOut.length()-(p.length()-prefixIn.length()));
|
692 | suffixOut = suffixOut.substring(s.length()-suffixIn.length());
|
693 |
|
694 | //System.out.println("[after last info] " + quote(prefixIn) + " " + quote(suffixIn) + " " + quote(prefixOut) + " " + quote(suffixOut));
|
695 | String core = in.substring(prefixIn.length(), in.length()-suffixIn.length());
|
696 | return prefixOut + core + suffixOut;
|
697 | }
|
698 |
|
699 | public void toJava(Code code) {
|
700 | if (prefixIn.length() != 0 || suffixIn.length() != 0)
|
701 | code.line(code.var + " = ((String) " + code.var + ").substring(" + prefixIn.length() + ", " + code.s() + ".length()-" + suffixIn.length() + ");");
|
702 | if (prefixOut.length() != 0 || suffixOut.length() != 0)
|
703 | code.line(code.var + " = " + quote(prefixOut) + " + " + code.var + " + " + quote(suffixOut) + ";");
|
704 | }
|
705 |
|
706 | void printState(String text) {
|
707 | System.out.println(text);
|
708 | printVars();
|
709 | }
|
710 | }
|
711 |
|
712 | // for "find" tasks (e.g. "abcde" to "[[abc]]de")
|
713 | static class LInputPattern implements Learner {
|
714 | String regexp = "";
|
715 |
|
716 | public void processInOut(Object _in, Object _out) {
|
717 | String in = (String) _in, out = (String) _out;
|
718 | int i = out.indexOf("[["), j = out.indexOf("]]", i+1);
|
719 | if (j < 0) return;
|
720 | String s = out.substring(i+2, j);
|
721 | regexp = s.replaceAll("\\d+", Matcher.quoteReplacement("\\d+"));
|
722 | System.out.println("regexp: " + regexp);
|
723 | }
|
724 |
|
725 | public String processIn(Object _in) {
|
726 | String in = (String) _in;
|
727 | if (regexp.length() == 0)
|
728 | return in;
|
729 | else
|
730 | return in.replaceAll("(" + regexp + ")", "[[$1]]");
|
731 | }
|
732 |
|
733 | public void toJava(Code code) {
|
734 | code.line(code.var + " = ((String) " + code.var + ").replaceAll(" + quote("(" + regexp + ")") + ", \"[[$1]]\");");
|
735 | }
|
736 | }
|
737 |
|
738 | static class LFixed extends LearnerImpl {
|
739 | static boolean debug;
|
740 | Object value;
|
741 |
|
742 | public void processInOut(Object in, Object out) {
|
743 | value = out;
|
744 | if (debug)
|
745 | printVars();
|
746 | }
|
747 |
|
748 | public Object processIn(Object in) {
|
749 | return value;
|
750 | }
|
751 |
|
752 | public void toJava(Code code) {
|
753 | code.line(code.var + " = " + quote((String) value) + ";");
|
754 | }
|
755 | }
|
756 |
|
757 | static void fail(String msg) {
|
758 | throw new RuntimeException(msg);
|
759 | }
|
760 |
|
761 | static void assertSameSize(List a, List b) {
|
762 | if (a.size() != b.size())
|
763 | fail("wrong list sizes");
|
764 | }
|
765 |
|
766 | // process lists in parallel
|
767 | // (in and out must be a list of same length)
|
768 | static class LEach extends LearnerImpl {
|
769 | static boolean debug;
|
770 | Learner base;
|
771 |
|
772 | LEach(Learner base) {
|
773 | this.base = base;
|
774 | }
|
775 |
|
776 | public void processInOut(Object _in, Object _out) {
|
777 | List in = (List) _in, out = (List) _out;
|
778 | assertSameSize(in, out);
|
779 | for (int i = 0; i < in.size(); i++)
|
780 | base.processInOut(in.get(i), out.get(i));
|
781 | if (debug)
|
782 | printVars();
|
783 | }
|
784 |
|
785 | public Object processIn(Object _in) {
|
786 | List in = (List) _in;
|
787 | List out = new ArrayList();
|
788 | for (Object x : in)
|
789 | out.add(base.processIn(x));
|
790 | return out;
|
791 | }
|
792 |
|
793 | public void toJava(Code code) {
|
794 | code.line("List out = new ArrayList();");
|
795 | code.line("for (Object x : (List) in) {");
|
796 | code.indent();
|
797 | code.line("in = x;");
|
798 | base.toJava(code);
|
799 | code.line("out.add(in);");
|
800 | code.unindent();
|
801 | code.line("}");
|
802 | code.line("in = out;");
|
803 | }
|
804 | }
|
805 |
|
806 | static class LChange extends LearnerImpl {
|
807 | Function f;
|
808 | Learner base;
|
809 |
|
810 | LChange(Function f, Learner base) {
|
811 | this.f = f;
|
812 | this.base = base;
|
813 | }
|
814 |
|
815 | public void processInOut(Object in, Object out) {
|
816 | in = f.process(in);
|
817 | base.processInOut(in, out);
|
818 | }
|
819 |
|
820 | public Object processIn(Object in) {
|
821 | in = f.process(in);
|
822 | return base.processIn(in);
|
823 | }
|
824 |
|
825 | public void toJava(Code code) {
|
826 | f.toJava_process(code);
|
827 | base.toJava(code);
|
828 | }
|
829 | }
|
830 |
|
831 | static class LBoth extends LearnerImpl {
|
832 | ReversibleFunction f;
|
833 | Learner base;
|
834 |
|
835 | LBoth(ReversibleFunction f, Learner base) {
|
836 | this.f = f;
|
837 | this.base = base;
|
838 | }
|
839 |
|
840 | public void processInOut(Object in, Object out) {
|
841 | in = f.process(in);
|
842 | out = f.process(out);
|
843 | base.processInOut(in, out);
|
844 | }
|
845 |
|
846 | public Object processIn(Object in) {
|
847 | in = f.process(in);
|
848 | in = base.processIn(in);
|
849 | in = f.unprocess(in);
|
850 | return in;
|
851 | }
|
852 |
|
853 | public void toJava(Code code) {
|
854 | f.toJava_process(code);
|
855 | base.toJava(code);
|
856 | f.toJava_unprocess(code);
|
857 | }
|
858 | }
|
859 |
|
860 | static class RFJavaTok implements ReversibleFunction {
|
861 | public Object process(Object in) {
|
862 | return JavaTok.split((String) in);
|
863 | }
|
864 |
|
865 | public Object unprocess(Object in) {
|
866 | return JavaTok.join((List) in);
|
867 | }
|
868 |
|
869 | public void toJava_process(Code code) {
|
870 | code.translators("!636", "!class JavaTok");
|
871 | code.line(code.var + " = JavaTok.split((String) " + code.var + ");");
|
872 | }
|
873 |
|
874 | public void toJava_unprocess(Code code) {
|
875 | code.translators("!636", "!class JavaTok");
|
876 | code.line(code.var + " = JavaTok.join((List) " + code.var + ");");
|
877 | }
|
878 | }
|
879 |
|
880 | // works on a token list - makes a list of only the string constants (unquoted)
|
881 | static class FStringsOnly implements Function {
|
882 | static boolean debug;
|
883 |
|
884 | public Object process(Object _in) {
|
885 | new List<String> tok;
|
886 | for (String s : (List<String>) _in) {
|
887 | boolean isString = s.startsWith("\"") || s.startsWith("[[");
|
888 | if (isString)
|
889 | tok.add(unquote(s));
|
890 | if (debug)
|
891 | System.out.println("FStringsOnly - isString: " + isString + " - " + s);
|
892 | }
|
893 | return tok;
|
894 | }
|
895 |
|
896 | public void toJava_process(Code code) {
|
897 | code.translators("!standard functions");
|
898 | code.line("List<String> tok = new ArrayList<String>();");
|
899 | code.line("for (String s : (List<String>) " + code.var + ")");
|
900 | code.line(" if (s.startsWith(\"\\\"\") || s.startsWith(\"[[\")) tok.add(unquote(s));");
|
901 | code.assign("tok");
|
902 | }
|
903 | }
|
904 |
|
905 | // works on a token list - makes a list of only the number constants
|
906 | static class FNumbersOnly implements Function {
|
907 | static boolean debug;
|
908 |
|
909 | public Object process(Object _in) {
|
910 | new List<String> tok;
|
911 | for (String s : (List<String>) _in) {
|
912 | boolean isNumber = s.length() != 0 && (Character.isDigit(s.charAt(0)) || (s.charAt(0) == '-' && s.length() > 1));
|
913 | if (isNumber)
|
914 | tok.add(s);
|
915 | if (debug)
|
916 | System.out.println("FNumbersOnly - isNumber: " + isNumber + " - " + s);
|
917 | }
|
918 | return tok;
|
919 | }
|
920 |
|
921 | public void toJava_process(Code code) {
|
922 | code.line("List<String> tok = new ArrayList<String>();");
|
923 | code.line("for (String s : (List<String>) " + code.var + ")");
|
924 | code.line(" if (s.length() != 0 && (Character.isDigit(s.charAt(0)) || (s.charAt(0) == '-' && s.length() > 1))) tok.add(s);");
|
925 | code.assign("tok");
|
926 | }
|
927 | }
|
928 |
|
929 | static class LFixedFunction extends LearnerImpl {
|
930 | Function f;
|
931 |
|
932 | LFixedFunction(Function f) {
|
933 | this.f = f;
|
934 | }
|
935 |
|
936 | public void processInOut(Object in, Object out) {
|
937 | }
|
938 |
|
939 | public Object processIn(Object in) {
|
940 | return f.process(in);
|
941 | }
|
942 |
|
943 | public void toJava(Code code) {
|
944 | f.toJava_process(code);
|
945 | }
|
946 | }
|
947 |
|
948 | // trivial stuff like taking the one element out of a 1-element list
|
949 | static class LTrivial extends LearnerImpl {
|
950 | public void processInOut(Object in, Object out) {
|
951 | }
|
952 |
|
953 | public Object processIn(Object in) {
|
954 | return ((List) in).get(0);
|
955 | }
|
956 |
|
957 | public void toJava(Code code) {
|
958 | code.assign(code.list() + ".get(0)");
|
959 | }
|
960 | }
|
961 |
|
962 | // get element of a list at fixed index
|
963 | static class LGetListElement extends LearnerImpl {
|
964 | static boolean debug;
|
965 | int i;
|
966 |
|
967 | public void processInOut(Object _in, Object out) {
|
968 | List in = (List) _in;
|
969 | i = in.indexOf(out);
|
970 | if (debug)
|
971 | System.out.println("LGetListElement: " + i + " " + out);
|
972 | }
|
973 |
|
974 | public Object processIn(Object in) {
|
975 | return ((List) in).get(i);
|
976 | }
|
977 |
|
978 | public void toJava(Code code) {
|
979 | code.assign(code.list() + ".get(" + i + ")");
|
980 | }
|
981 | }
|
982 |
|
983 | // math operations
|
984 | static class LMath extends LearnerImpl {
|
985 | static boolean debug;
|
986 | String allOperations = "+ - * /";
|
987 | new (Tree)Set<String> possibleOperations;
|
988 |
|
989 | LMath() {
|
990 | possibleOperations.addAll(Arrays.asList(allOperations.split(" +")));
|
991 | }
|
992 |
|
993 | public void processInOut(Object _in, Object _out) {
|
994 | List in = (List) _in;
|
995 | String out = (String) _out;
|
996 | BigInteger[] inNumbers = getNumbers(in);
|
997 | BigInteger[] outNumbers = new BigInteger[] {getNumber(out)};
|
998 | findOperation(inNumbers, outNumbers);
|
999 | if (debug)
|
1000 | System.out.println("Operations: " + possibleOperations);
|
1001 | }
|
1002 |
|
1003 | public void findOperation(BigInteger[] in, BigInteger[] out) {
|
1004 | filterOperations(in, out);
|
1005 | if (possibleOperations.isEmpty())
|
1006 | fail("tilt");
|
1007 | }
|
1008 |
|
1009 | public void filterOperations(BigInteger[] in, BigInteger[] out) {
|
1010 | for (Iterator<String> i = possibleOperations.iterator(); i.hasNext(); ) {
|
1011 | String op = i.next();
|
1012 | BigInteger[] out2 = doOperation(op, in);
|
1013 | if (out2 == null || !arraysEqual(out, out2))
|
1014 | i.remove(); // keep only matching operations
|
1015 | }
|
1016 | }
|
1017 |
|
1018 | public BigInteger[] doOperation(String op, BigInteger[] in) {
|
1019 | op = op.intern();
|
1020 | try {
|
1021 | if (in.length == 2) {
|
1022 | BigInteger a = in[0], b = in[1], x = null;
|
1023 | if (op == "+")
|
1024 | x = a.add(b);
|
1025 | else if (op == "-")
|
1026 | x = a.subtract(b);
|
1027 | else if (op == "*")
|
1028 | x = a.multiply(b);
|
1029 | else if (op == "/")
|
1030 | x = a.divide(b);
|
1031 | return x != null ? new BigInteger[] {x} : null;
|
1032 | }
|
1033 | return null;
|
1034 | } catch (Throwable e) {
|
1035 | return null;
|
1036 | }
|
1037 | }
|
1038 |
|
1039 | public String processIn(Object _in) {
|
1040 | List<String> in = (List<String>) _in;
|
1041 | String op = possibleOperations.iterator().next();
|
1042 | if (debug)
|
1043 | System.out.println("op: " + op);
|
1044 | BigInteger[] inNumbers = getNumbers(in);
|
1045 | BigInteger[] outNumbers = doOperation(op, inNumbers);
|
1046 | return outNumbers[0].toString();
|
1047 | }
|
1048 |
|
1049 | String BI = BigInteger.class.getName();
|
1050 |
|
1051 | public void toJava(Code code) {
|
1052 | String op = possibleOperations.iterator().next();
|
1053 | String a = "new " + BI + "((String) " + code.list() + ".get(0))";
|
1054 | String b = "new " + BI + "((String) " + code.list() + ".get(1))";
|
1055 | if (op.equals("+"))
|
1056 | code.assign(a + ".add(" + b + ").toString()");
|
1057 | else
|
1058 | todo();
|
1059 | }
|
1060 |
|
1061 | static BigInteger[] getNumbers(List<String> in) {
|
1062 | BigInteger[] big = new BigInteger[in.size()];
|
1063 | for (int i = 0; i < in.size(); i++)
|
1064 | big[i] = new BigInteger(in.get(i));
|
1065 | return big;
|
1066 | }
|
1067 |
|
1068 | static BigInteger getNumber(String s) {
|
1069 | return new BigInteger(s);
|
1070 | }
|
1071 |
|
1072 | static boolean arraysEqual(BigInteger[] a, BigInteger[] b) {
|
1073 | if (a.length != b.length) return false;
|
1074 | for (int i = 0; i < a.length; i++)
|
1075 | if (!a[i].equals(b[i])) return false;
|
1076 | return true;
|
1077 | }
|
1078 | }
|
1079 |
|
1080 | static class EscapeCase implements Function {
|
1081 | static boolean debug;
|
1082 |
|
1083 | public Object process(Object _in) {
|
1084 | if (debug)
|
1085 | System.out.println("EscapeCase: " + _in);
|
1086 | String in = (String) _in;
|
1087 | return in.equals("case") ? "_case" : in;
|
1088 | }
|
1089 |
|
1090 | public void toJava_process(Code code) {
|
1091 | code.line("if (\"case\".equals(" + code.var + ")) " + code.var + " = " + quote("_case") + ";");
|
1092 | }
|
1093 | }
|
1094 |
|
1095 | static class LCharShift extends LearnerImpl {
|
1096 | int shift;
|
1097 |
|
1098 | public void processInOut(Object _in, Object _out) {
|
1099 | String in = (String) _in, out = (String) _out;
|
1100 | shift = (int) out.charAt(0) - (int) in.charAt(0);
|
1101 | }
|
1102 |
|
1103 | public Object processIn(Object _in) {
|
1104 | String in = (String) _in;
|
1105 | char[] c = new char[in.length()];
|
1106 | for (int i = 0; i < c.length; i++)
|
1107 | c[i] = (char) ((int) in.charAt(i) + shift);
|
1108 | return new String(c);
|
1109 | }
|
1110 |
|
1111 | public void toJava(Code code) {
|
1112 | code.line("char[] c = new char[((String) " + code.var + ").length()];");
|
1113 | code.line("for (int i = 0; i < c.length; i++)");
|
1114 | code.line(" c[i] = (char) ((int) ((String) " + code.var + ").charAt(i)" + (shift < 0 ? "" + shift : "+" + shift) + ");");
|
1115 | code.line(code.var + " = new String(c);");
|
1116 | }
|
1117 | }
|
1118 |
|
1119 | // applies base learner to first char of string
|
1120 | // (or first element of list, TODO)
|
1121 | static class LFirst implements Learner {
|
1122 | Learner baseLearner;
|
1123 |
|
1124 | LFirst(Learner baseLearner) {
|
1125 | this.baseLearner = baseLearner;
|
1126 | }
|
1127 |
|
1128 | public void processInOut(Object _in, Object _out) {
|
1129 | String in = (String) _in, out = (String) _out;
|
1130 | if (in.length() == 0)
|
1131 | return;
|
1132 | String firstIn = in.substring(0, 1), firstOut = out.substring(0, 1);
|
1133 | baseLearner.processInOut(firstIn, firstOut);
|
1134 | }
|
1135 |
|
1136 | public Object processIn(Object _in) {
|
1137 | String in = (String) _in;
|
1138 | if (in.length() == 0)
|
1139 | return in;
|
1140 | String firstIn = in.substring(0, 1);
|
1141 | return baseLearner.processIn(firstIn) + in.substring(1);
|
1142 | }
|
1143 |
|
1144 | public void toJava(Code code) {
|
1145 | code.line("if (" + code.s() + ".length() != 0) {");
|
1146 | code.indent();
|
1147 | code.line("String rest = " + code.s() + ".substring(1);");
|
1148 | code.line(code.var + " = " + code.s() + ".substring(0, 1);");
|
1149 | baseLearner.toJava(code);
|
1150 | code.line(code.var + " = " + code.s() + "+rest;");
|
1151 | code.unindent();
|
1152 | code.line("}");
|
1153 | }
|
1154 | }
|
1155 |
|
1156 | static Method findMainMethod(Class<?> theClass) {
|
1157 | for (Method method : theClass.getMethods())
|
1158 | if (method.getName().equals("main") && method.getParameterTypes().length == 1)
|
1159 | return method;
|
1160 | throw new RuntimeException("Method 'main' with 1 parameter not found in " + theClass.getName());
|
1161 | }
|
1162 |
|
1163 | // compile JavaX source and load main class
|
1164 | static Class<?> loadMainClass(String src) tex {
|
1165 | File srcDir = _x16.TempDirMaker_make();
|
1166 | File classesDir = _x16.TempDirMaker_make();
|
1167 | _x16.saveTextFile(new File(srcDir, "main.java").getPath(), src);
|
1168 | new List<File> libraries;
|
1169 | File transpiledDir = _x16.topLevelTranslate(srcDir, libraries);
|
1170 | String javacOutput = _x16.compileJava(transpiledDir, libraries, classesDir);
|
1171 | System.out.println(javacOutput);
|
1172 | URL[] urls = {classesDir.toURI().toURL()};
|
1173 |
|
1174 | // make class loader
|
1175 | URLClassLoader classLoader = new URLClassLoader(urls);
|
1176 |
|
1177 | // load main class
|
1178 | Class<?> mainClass = classLoader.loadClass("main");
|
1179 | return mainClass;
|
1180 | }
|
1181 |
|
1182 | static Method compileJavaInToOut(Code code) {
|
1183 | try {
|
1184 | String java = code.buf.toString();
|
1185 | String prelude = /*"import java.util.*;\n\n" +*/
|
1186 | "public class main { public static Object main(Object in) throws Exception {\n";
|
1187 | String postlude = "\nreturn in;\n}}";
|
1188 | String src = code.getTranslators() + "\n" + prelude + java + postlude;
|
1189 | Class<?> mainClass = loadMainClass(src);
|
1190 | return findMainMethod(mainClass);
|
1191 | } catch (Exception e) {
|
1192 | throw new RuntimeException(e);
|
1193 | }
|
1194 | }
|
1195 |
|
1196 | static Method findCalcMethod(Class<?> theClass) {
|
1197 | for (Method method : theClass.getMethods())
|
1198 | if (method.getName().equals("calc"))
|
1199 | return method;
|
1200 | throw new RuntimeException("Method 'calc' not found in " + theClass.getName());
|
1201 | }
|
1202 |
|
1203 | // for simplejava stuff (execute tasks)
|
1204 | static String execute(String src) {
|
1205 | try {
|
1206 | Class<?> mainClass = loadMainClass(src);
|
1207 | Method m = findCalcMethod(mainClass);
|
1208 | return String.valueOf(m.invoke(null));
|
1209 | } catch (Exception e) {
|
1210 | throw new RuntimeException(e);
|
1211 | }
|
1212 | }
|
1213 |
|
1214 | static void testJava(Case case, Code code) {
|
1215 | try {
|
1216 | Method m = compileJavaInToOut(code);
|
1217 |
|
1218 | for (String[] e : case.fullExamples) {
|
1219 | String out = (String) m.invoke(null, e[0]);
|
1220 |
|
1221 | if (!e[1].equals(out)) {
|
1222 | throw new RuntimeException("[fail] Java code on " + quote(e[0]) + " - got: " + quote(out) + " rather than: " + quote(e[1]));
|
1223 | }
|
1224 | }
|
1225 |
|
1226 | System.out.println("\nGOOD JAVA.");
|
1227 | case.goodJava = true;
|
1228 | } catch (Throwable e) {
|
1229 | if (showFails)
|
1230 | e.printStackTrace();
|
1231 | System.out.println("\nBAD JAVA.");
|
1232 | }
|
1233 | }
|
1234 |
|
1235 | static void todo() {
|
1236 | fail("todo");
|
1237 | }
|
1238 |
|
1239 | static class LSwitch extends LearnerImpl {
|
1240 | Case case;
|
1241 | Learner switcher;
|
1242 |
|
1243 | LSwitch(Case case, Learner switcher) {
|
1244 | this.case = case;
|
1245 | this.switcher = switcher;
|
1246 | }
|
1247 |
|
1248 | public void processInOut(Object in, Object out) {
|
1249 | }
|
1250 |
|
1251 | public Object processIn(Object in) {
|
1252 | int i = Integer.parseInt((String) switcher.processIn(in));
|
1253 | return case.combined.get(i-1).winner.processIn(in);
|
1254 | }
|
1255 |
|
1256 | public void toJava(Code code) {
|
1257 | todo();
|
1258 | }
|
1259 | }
|
1260 |
|
1261 | static class LTryPrevious extends LearnerImpl {
|
1262 | new List<Case> candidates;
|
1263 |
|
1264 | LTryPrevious() {
|
1265 | for (int i = caseIdx-1; i >= 0; i--)
|
1266 | candidates.add(cases.get(i));
|
1267 | }
|
1268 |
|
1269 | public void processInOut(Object _in, Object _out) {
|
1270 | String in = (String) _in, out = (String) _out;
|
1271 | for (ListIterator<Case> i = candidates.listIterator(); i.hasNext(); ) {
|
1272 | Case case = i.next();
|
1273 | if (case.winner == null || !validate(new String[] {in, out}, case.winner))
|
1274 | i.remove();
|
1275 | }
|
1276 | if (candidates.isEmpty())
|
1277 | fail("no previous solution found");
|
1278 | }
|
1279 |
|
1280 | public Object processIn(Object in) {
|
1281 | return candidates.get(0).winner.processIn(in);
|
1282 | }
|
1283 |
|
1284 | public void toJava(Code code) {
|
1285 | candidates.get(0).winner.toJava(code);
|
1286 | }
|
1287 | }
|
1288 |
|
1289 | static class LMulti extends LearnerImpl implements Retry {
|
1290 | static boolean debug;
|
1291 | new List<Learner> candidates;
|
1292 |
|
1293 | LMulti(Learner... learners) {
|
1294 | for (Learner l : learners)
|
1295 | candidates.add(l);
|
1296 | }
|
1297 |
|
1298 | LMulti(L<Learner> learners) {
|
1299 | for (Learner l : learners)
|
1300 | candidates.add(l);
|
1301 | }
|
1302 |
|
1303 | public void processInOut(Object in, Object out) {
|
1304 | if (debug)
|
1305 | System.err.println("LMulti candidates: " + candidates.size());
|
1306 | for (ListIterator<Learner> i = candidates.listIterator(); i.hasNext(); ) {
|
1307 | Learner l = i.next();
|
1308 | try {
|
1309 | l.processInOut(in, out);
|
1310 | } catch (Throwable e) {
|
1311 | if (debug) {
|
1312 | e.printStackTrace();
|
1313 | System.err.println("Removing candidate: " + structure(l));
|
1314 | }
|
1315 | silentException(e);
|
1316 | i.remove();
|
1317 | }
|
1318 | }
|
1319 | if (debug)
|
1320 | System.err.println("LMulti candidates now: " + candidates.size());
|
1321 | if (candidates.isEmpty())
|
1322 | fail("no candidates left");
|
1323 | }
|
1324 |
|
1325 | public Object processIn(Object in) {
|
1326 | while (true) { // fails or returns eventually
|
1327 | Learner l = candidates.get(0);
|
1328 | if (debug)
|
1329 | System.err.println("Using candidate: " + structure(l) + ", " + candidates.size() + " left");
|
1330 | try {
|
1331 | return l.processIn(in);
|
1332 | } catch (Throwable e) {
|
1333 | if (debug) {
|
1334 | e.printStackTrace();
|
1335 | System.err.println("Removing candidate: " + structure(l));
|
1336 | }
|
1337 | silentException(e);
|
1338 | candidates.remove(0);
|
1339 | }
|
1340 | }
|
1341 | }
|
1342 |
|
1343 | public void toJava(Code code) {
|
1344 | candidates.get(0).toJava(code);
|
1345 | }
|
1346 | }
|
1347 |
|
1348 | static String structure(Object o) {
|
1349 | //if (!(o instanceof Base))
|
1350 | if (!o.getClass().getName().startsWith("main$"))
|
1351 | return String.valueOf(o);
|
1352 |
|
1353 | new StringBuilder buf;
|
1354 |
|
1355 | // TODO: go to superclasses too
|
1356 | Field[] fields = o.getClass().getDeclaredFields();
|
1357 | for (Field field : fields) {
|
1358 | if ((field.getModifiers() & Modifier.STATIC) != 0)
|
1359 | continue;
|
1360 | Object value;
|
1361 | try {
|
1362 | value = field.get(o);
|
1363 | } catch (Exception e) {
|
1364 | value = "?";
|
1365 | }
|
1366 |
|
1367 | if (!buf.isEmpty()) buf.append(", ");
|
1368 | buf.append(field.getName() + "=" + structure(value));
|
1369 | }
|
1370 | String s = o.getClass().getName().replaceAll("^main\\$", "");
|
1371 | if (!buf.isEmpty())
|
1372 | s += "(" + buf + ")";
|
1373 | return s;
|
1374 | }
|
1375 |
|
1376 | static class FIsString implements Function {
|
1377 | static boolean debug;
|
1378 |
|
1379 | public Object process(Object _in) {
|
1380 | String in = (String) _in;
|
1381 | return in.startsWith("\"") || in.startsWith("[[") ? "1" : "0";
|
1382 | }
|
1383 |
|
1384 | public void toJava_process(Code code) {
|
1385 | code.assign(code.s() + ".startsWith(\"\\\"\") || " + code.s() + ".startsWith(\"[[\") ? \"1\" : \"0\"");
|
1386 | }
|
1387 | }
|
1388 |
|
1389 | /*static class Pair {
|
1390 | Object a, b;
|
1391 |
|
1392 | public boolean equals(Object o) {
|
1393 | return o instanceof Pair && a.equals(((Pair) o).a) && b.equals((Pair) o).b);
|
1394 | }
|
1395 |
|
1396 | public int hashCode() {
|
1397 | return a.hashCode()+b.hashCode()*2;
|
1398 | }
|
1399 | }*/
|
1400 |
|
1401 | static class Matrix {
|
1402 | new HashMap<Object, Map> dataByCol;
|
1403 |
|
1404 | void put(Object col, Object row, Object value) {
|
1405 | //data.put(new Pair(col, row), value);
|
1406 | getCol(col).put(row, value);
|
1407 | }
|
1408 |
|
1409 | Map getCol(Object col) {
|
1410 | Map map = dataByCol.get(col);
|
1411 | if (map == null)
|
1412 | dataByCol.put(col, map = new HashMap());
|
1413 | return map;
|
1414 | }
|
1415 |
|
1416 | Object get(Object col, Object row) {
|
1417 | //return data.get(new Pair(col, row));
|
1418 | return getCol(col).get(row);
|
1419 | }
|
1420 |
|
1421 | Set cols() {
|
1422 | return dataByCol.keySet();
|
1423 | }
|
1424 |
|
1425 | Set rowsFor(Object col) {
|
1426 | return getCol(col).keySet();
|
1427 | }
|
1428 | }
|
1429 |
|
1430 | static class LDistinguishList extends LearnerImpl {
|
1431 | static boolean debug;
|
1432 | Function helper;
|
1433 | int idx;
|
1434 | new Matrix matrix;
|
1435 |
|
1436 | LDistinguishList(Function helper) {
|
1437 | this.helper = helper;
|
1438 | }
|
1439 |
|
1440 | public void processInOut(Object _in, Object out) {
|
1441 | List in = (List) _in;
|
1442 | for (int i = 0; i < in.size(); i++) {
|
1443 | Object y = helper.process(in.get(i));
|
1444 | matrix.put(i, y, out);
|
1445 | }
|
1446 | }
|
1447 |
|
1448 | public Object processIn(Object _in) {
|
1449 | // find idx
|
1450 |
|
1451 | for (Object i : matrix.cols()) {
|
1452 | Collection ys = matrix.rowsFor(i);
|
1453 | if (ys.size() > 1) {
|
1454 | idx = (Integer) i;
|
1455 | break;
|
1456 | }
|
1457 | }
|
1458 |
|
1459 | List in = (List) _in;
|
1460 | Object y = helper.process(in.get(idx));
|
1461 | return matrix.get(idx, y);
|
1462 | }
|
1463 |
|
1464 | public void toJava(Code code) {
|
1465 | List ys = new ArrayList(matrix.rowsFor(idx));
|
1466 | //String v = code.var;
|
1467 | //code.newVar();
|
1468 | //String vy = code.var;
|
1469 | //code.oldVar();
|
1470 | code.assign(code.list() + ".get(" + idx + ")");
|
1471 | helper.toJava_process(code);
|
1472 |
|
1473 | for (int i = 0; i < ys.size(); i++) {
|
1474 | Object y = ys.get(i);
|
1475 | if (i < ys.size())
|
1476 | code.line((i == 0 ? "" : "else ") + "if (" + quote((String) y) + ".equals(" + code.var + "))");
|
1477 | else
|
1478 | code.line("else");
|
1479 | code.line(" " + code.var + " = " + quote((String) matrix.get(idx, y)) + ";");
|
1480 | }
|
1481 | }
|
1482 | }
|
1483 |
|
1484 | static class LBox extends LearnerImpl {
|
1485 | static boolean debug;
|
1486 | Learner middleLearner;
|
1487 | char topChar, bottomChar;
|
1488 |
|
1489 | LBox(Learner middleLearner) {
|
1490 | this.middleLearner = middleLearner;
|
1491 | }
|
1492 |
|
1493 | public void processInOut(Object _in, Object _out) {
|
1494 | String in = (String) _in, out = (String) _out;
|
1495 | L<S> l = toLines(out);
|
1496 | String middle = l.get(2);
|
1497 | middleLearner.processInOut(in, middle);
|
1498 | topChar = l.get(1).charAt(0);
|
1499 | bottomChar = l.get(3).charAt(0);
|
1500 | }
|
1501 |
|
1502 | public Object processIn(Object in) {
|
1503 | String middle = (String) middleLearner.processIn(in);
|
1504 | return "\n" +
|
1505 | repeat(topChar, middle.length()) + "\n" +
|
1506 | middle + "\n" +
|
1507 | repeat(bottomChar, middle.length()) + "\n";
|
1508 | }
|
1509 |
|
1510 | static String repeat(char c, int n) {
|
1511 | char[] chars = new char[n];
|
1512 | for (int i = 0; i < n; i++)
|
1513 | chars[i] = c;
|
1514 | return new String(chars);
|
1515 | }
|
1516 |
|
1517 | public void toJava(Code code) {
|
1518 | todo();
|
1519 | }
|
1520 | }
|
1521 | } |