sclass Puzzler { new L remainingTokens; new L numbers; new L vars; bool aggressiveFirst = true; bool useAllTokens = true; int maxTries = 1000; bool initVars = true; S code = ""; *(S tokens) { for (S s : codeTokens(javaTok(tokens))) if (eq(s, "i") || eq(s, "j")) { vars.add(s); if (initVars) code += s + " = 0\n"; } else if (isInteger(s)) numbers.add(s); else remainingTokens.add(s); } S var() { ret oneOf(vars); } S exp() { /*int i = random(2); S s = "?"; switch (i) { case 0: s = "0"; case 1: s = "9"; }*/ S s = oneOf(concatLists(numbers, vars)); if (random(3) == 0) s = "get(" + s + ")"; ret s; } S swap() { ret "swap(" + exp() + ", " + exp() + ")\n"; } S _for() { ret "for " + var() + " = " + exp() + ", " + exp() + "-1 do\n" + indentx(code()) + "end\n"; } S ifless() { ret "if " + exp() + " < " + exp() + " then\n" + indentx(code()) + "end\n"; } S code() { S s = choose("swap", "for", "ifless"); if (s == null) ret ""; ret (S) call(this, eq(s, "for") ? "_for" : s); /*if (eq(s, "swap")) ret swap(); if (eq(s, "for")) ret for();*/ } S main() { if (useAllTokens) ret code + code(); L tokens = cloneList(remainingTokens); for (int i = 0; i < maxTries; i++) { remainingTokens = cloneList(tokens); S s = code(); if (empty(remainingTokens)) ret code + s; } throw fail("Can't solve using all tokens: " + structure(tokens)); } S choose(S... options) { new L l; if (aggressiveFirst && nempty(remainingTokens) && contains(options, first(remainingTokens))) { S s = first(remainingTokens); remainingTokens.remove(0); ret s; } for (S s : options) if (remainingTokens.contains(s)) l.add(s); S choice = oneOf(l); if (choice != null) remainingTokens.remove(choice); ret choice; } } /* for(variable, exp, exp, code) -> code ifless(exp, exp, code) -> code swap(exp, exp) -> code variable -> exp number -> exp get(exp) -> exp // << always available, at least one level deep */