1 | !636
|
2 | !quickmain
|
3 | !auto-import
|
4 | !standard functions
|
5 |
|
6 | interface Learner {
|
7 | void processInOut(String in, String out);
|
8 | String processIn(String in);
|
9 | void toJava(Code code);
|
10 | }
|
11 |
|
12 | class Code {
|
13 | StringBuilder buf = new StringBuilder();
|
14 |
|
15 | void line(String line) {
|
16 | buf.append(line).append('\n');
|
17 | }
|
18 | }
|
19 |
|
20 | main {
|
21 | static List<String[]> fullExamples = new ArrayList<String[]>();
|
22 | static List<String> halfExamples = new ArrayList<String>();
|
23 | static List<String[]> examples1, examples2;
|
24 |
|
25 | psvm {
|
26 | parse(args.length != 0 ? args[0] : null);
|
27 | calculate();
|
28 | }
|
29 |
|
30 | static void parse(String arg) tex {
|
31 | String text;
|
32 | if (arg != null)
|
33 | text = loadSnippet(arg);
|
34 | else {
|
35 | text = loadTextFile("input/input.txt", null);
|
36 | if (text == null) text = loadSnippet("#2000454"); // example input
|
37 | }
|
38 |
|
39 | System.out.println(text);
|
40 | String in = null, out = null;
|
41 |
|
42 | for (String line : toLines(text)) {
|
43 | if (line.startsWith("I")) { // "In: " or "I: "
|
44 | if (in != null)
|
45 | halfExamples.add(in);
|
46 | in = unquote(line.substring(line.indexOf(':')+1).trim());
|
47 | out = null;
|
48 | } else if (line.startsWith("O")) { // "Out: " or "O: "
|
49 | out = unquote(line.substring(line.indexOf(':')+1).trim());
|
50 | System.out.println(quote(in) + " => " + quote(out));
|
51 | fullExamples.add(new String[] {in, out});
|
52 | in = out = null;
|
53 | }
|
54 | }
|
55 |
|
56 | if (in != null)
|
57 | halfExamples.add(in);
|
58 | }
|
59 |
|
60 | static void calculate() tex {
|
61 | if (fullExamples.size() < 2)
|
62 | throw new RuntimeException("Too few examples (" + fullExamples.size() + ")");
|
63 | int splitPoint = fullExamples.size()-1;
|
64 | System.out.println("Full examples: " + fullExamples.size() + ", splitPoint: " + splitPoint);
|
65 | examples1 = fullExamples.subList(0, splitPoint);
|
66 | examples2 = fullExamples.subList(splitPoint, fullExamples.size());
|
67 |
|
68 | Learner learner = findOKLearner();
|
69 | if (learner == null)
|
70 | print "\nProblem not solved"
|
71 | else {
|
72 | print "\nSolved!\n"
|
73 | Code code = new Code();
|
74 | learner.toJava(code);
|
75 | System.out.println(code.buf);
|
76 | for (String in : halfExamples) {
|
77 | String out = learner.processIn(in);
|
78 | System.out.println(quote(in) + " =>! " + quote(out));
|
79 | }
|
80 | }
|
81 | }
|
82 |
|
83 | static Learner findOKLearner() {
|
84 | for (Learner learner : makeLearners()) try {
|
85 | if (learnerOK(learner))
|
86 | return learner;
|
87 | } catch (Throwable e) {
|
88 | e.printStackTrace();
|
89 | }
|
90 | return null;
|
91 | }
|
92 |
|
93 | static boolean learnerOK(Learner learner) {
|
94 | for (String[] e : examples1) {
|
95 | learner.processInOut(e[0], e[1]);
|
96 | }
|
97 | for (String[] e : fullExamples) {
|
98 | String out = learner.processIn(e[0]);
|
99 | if (!e[1].equals(out)) {
|
100 | System.out.println("[fail] " + learner + " on " + quote(e[0]) + " - " + quote(out) + " vs " + quote(e[1]));
|
101 | return false;
|
102 | }
|
103 | }
|
104 | return true; // all test examples passed
|
105 | }
|
106 |
|
107 | static Iterable<Learner> makeLearners() {
|
108 | List<Learner> list = new ArrayList<Learner>();
|
109 | //list.add(new LId()); // subsumed by trivial case of PrefixSuffix
|
110 | list.add(new LPrefixSuffix());
|
111 | list.add(new LSplitInput(new LOutPattern()));
|
112 | return list;
|
113 | }
|
114 |
|
115 | public static String unquote(String s) {
|
116 | if (s.startsWith("\"") && s.endsWith("\"") && s.length() > 1)
|
117 | return s.substring(1, s.length()-1).replace("\\\"", "\"").replace("\\\\", "\\"); // SHOULD work...
|
118 | else
|
119 | return s; // Return SOMETHING
|
120 | }
|
121 |
|
122 | public static String quote(String s) {
|
123 | if (s == null) return "null";
|
124 | return "\"" + s.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
|
125 | }
|
126 |
|
127 | // splits the input at some point, takes only one part
|
128 | static class LSplitInput implements Learner {
|
129 | int splitIdx = 1; // split after first character
|
130 | Learner baseLearner;
|
131 |
|
132 | LSplitInput(Learner baseLearner) {
|
133 | this.baseLearner = baseLearner;
|
134 | }
|
135 |
|
136 | public void processInOut(String in, String out) {
|
137 | in = in.substring(splitIdx);
|
138 | baseLearner.processInOut(in, out);
|
139 | }
|
140 |
|
141 | public String processIn(String in) {
|
142 | in = in.substring(splitIdx);
|
143 | return baseLearner.processIn(in);
|
144 | }
|
145 |
|
146 | public void toJava(Code code) {
|
147 | code.line("in = in.substring(" + splitIdx + ");");
|
148 | baseLearner.toJava(code);
|
149 | }
|
150 | }
|
151 |
|
152 | // if input appears in output in fixed pattern
|
153 | static class LOutPattern implements Learner {
|
154 | String pattern = "%!%";
|
155 |
|
156 | public void processInOut(String in, String out) {
|
157 | pattern = out.replace(in, "%!%");
|
158 | }
|
159 |
|
160 | public String processIn(String in) {
|
161 | return pattern.replace("%!%", in);
|
162 | }
|
163 |
|
164 | public void toJava(Code code) {
|
165 | code.line("in = " + quote(pattern) + ".replace(" + quote("%!%") + ", in);");
|
166 | }
|
167 | }
|
168 |
|
169 | // learns to exchange common prefixes and suffixes
|
170 | static class LPrefixSuffix implements Learner {
|
171 | String prefixIn, suffixIn, prefixOut, suffixOut;
|
172 |
|
173 | public void processInOut(String in, String out) {
|
174 | updateIn(in);
|
175 | prefixOut = prefixOut == null ? out : commonPrefix(prefixOut, out);
|
176 | suffixOut = suffixOut == null ? out : commonSuffix(suffixOut, out);
|
177 | }
|
178 |
|
179 | void updateIn(String in) {
|
180 | prefixIn = prefixIn == null ? in : commonPrefix(prefixIn, in);
|
181 | suffixIn = suffixIn == null ? in : commonSuffix(suffixIn, in);
|
182 | }
|
183 |
|
184 | public String processIn(String in) {
|
185 | //System.out.println("[before last info] " + quote(prefixIn) + " " + quote(suffixIn) + " " + quote(prefixOut) + " " + quote(suffixOut));
|
186 | //System.out.println("[last info] " + quote(in));
|
187 |
|
188 | // use latest information
|
189 | String p = prefixIn, s = suffixIn;
|
190 | updateIn(in);
|
191 | prefixOut = prefixOut.substring(0, prefixOut.length()-(p.length()-prefixIn.length()));
|
192 | suffixOut = suffixOut.substring(s.length()-suffixIn.length());
|
193 |
|
194 | //System.out.println("[after last info] " + quote(prefixIn) + " " + quote(suffixIn) + " " + quote(prefixOut) + " " + quote(suffixOut));
|
195 | String core = in.substring(prefixIn.length(), in.length()-suffixIn.length());
|
196 | return prefixOut + core + suffixOut;
|
197 | }
|
198 |
|
199 | public void toJava(Code code) {
|
200 | throw new RuntimeException("TODO");
|
201 | }
|
202 | }
|
203 |
|
204 | } |