!747 !multi-line strings m { static class Concept { new L stringExamples; new L descriptions; boolean closed; void addStringExample(S s) { if (!stringExamples.contains(s)) // yes it's inefficient... who cares right now :)))))) stringExamples.add(s); } void addDescription(S s) { if (!descriptions.contains(s)) descriptions.add(s); } } static class Concepts { new Map map; Concept get(S s) { Concept c = map.get(s); if (c == null) map.put(s, c = new Concept()); return c; } } static new Concepts concepts; p { L sentences = toLinesFullTrim([[ "0" is a digit. "1" is a digit. "2" is a digit. "3" is a digit. "4" is a digit. "5" is a digit. "6" is a digit. "7" is a digit. "8" is a digit. "9" is a digit. These are all the digits that exist. A number is a concatenation of digits. ]]); L questions = toLinesFullTrim([[ Is "5" a digit? Is "your mama" a digit? ]]); for (S s : concat(sentences, questions)) { L tok = javaTok(s); S[] bla = match("* is a *.", tok); if (bla != null && bla[0].startsWith("\"")) { print(bla[0] + " is a " + bla[1] + "!"); concepts.get(bla[1]).addStringExample(unquote(bla[0])); continue; } bla = match("These are all the * that exist.", tok); if (bla != null) { S c = bla[0].replaceAll("s$", ""); concepts.get(c).closed = true; print("Closed concept " + c + "."); continue; } bla = match2("A * is ... .", tok); if (bla != null) { S desc = joinrest(bla, 1); concepts.get(bla[0]).addDescription(desc); print(bla[0] + ": " + desc); continue; } // process questions on knowledge base bla = match2("Is * a *?", tok); if (bla != null) { print("? " + s); S answer = "Dunno."; Concept c = concepts.get(bla[1]); if (bla[0].startsWith("\"") && c.closed) { answer = c.stringExamples.contains(unquote(bla[0])) ? "Yes." : "No."; } print("! " + answer); continue; } print("Unknown line: " + s); } print("Number of concepts: " + concepts.map.size() + " (" + structure(concepts.map.keySet()) + ")"); } static S[] match(S pattern, L tok) { L pat = javaTok(pattern); return match(pat, tok); } static S[] match(L pat, L tok) { new L result; if (pat.size() != tok.size()) return null; for (int i = 1; i < pat.size(); i += 2) { S p = pat.get(i), t = tok.get(i); if (p == "*") result.add(t); else if (!p.equals(t)) return null; } return result.toArray(new S[result.size()]); } /* static class LL { S head; LL rest; } static LL match2(L pat, L inp, int i, int j) { boolean debug = false; if (i+j-1 >= inp.size()) return null; // fail for (; j < pat.size(); j += 2) { String p = pat.get(j); if (debug) System.out.println("step " + p + " " + inp.get(i+j-1)); if (p == "*") { // ok, consume } else if (p == "." && pat.get(j+2).equals(".") && pat.get(j+4).equals(".")) { LL bla = match2(pat, inp, i, j+6); // end ... if (bla != null) return bla; return match2(pat, inp, i+2, j); // continue ... } else { String found = inp.get(i + j - 1); if (!found.equals(p) return null; // fail } } return i+j-2; }*/ static S[] match2(S pattern, L tok) { L pat = javaTokPlusPeriod(pattern); // standard case (no ...) int i = pat.indexOf("..."); if (i < 0) return match(pat, tok); pat.set(i, "*"); int expand = 0; while (pat.size() < tok.size()) { ++expand; pat.add(i, "*"); pat.add(i+1, ""); // doesn't matter } return match(pat, tok); } static S joinrest(S[] bla, int i) { return join(" ", Arrays.asList(bla).subList(i, bla.length)); } static L concat(L a, L b) { L l = new ArrayList(a); l.addAll(b); return l; } }