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

231
LINES

< > BotCompany Repo | #1002072 // Conversion Bot (v2, LIVE)

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

Libraryless. Click here for Pure Java version (1711L/11K/37K).

1  
!752
2  
3  
// TODO: translator should accept this: "s/Rational/Rat" :-)
4  
5  
static S dataProgID = "#1002049"; // read/save data there
6  
7  
// Numeric quadruple
8  
static class NQ {
9  
  BigInteger a;
10  
  S b;
11  
  BigInteger c;
12  
  S d;
13  
  
14  
  *() {}
15  
  *(S a, S *b, S c, S *d) {
16  
    this.a = smartBigint(a);
17  
    this.c = smartBigint(c);
18  
  }
19  
  *(BigInteger *a, S *b, BigInteger *c, S *d) {}
20  
  
21  
  public boolean equals(O o) {
22  
    ret stdEq(this, o, "a", "b", "c", "d");
23  
  }
24  
  
25  
  public S toString() {
26  
    ret a + " " + b + " is " + c + " " + d;
27  
  }
28  
  
29  
  NQ reverse() {
30  
    ret new NQ(c, d, a, b);
31  
  }
32  
33  
  bool trivial() {
34  
    ret eq(b, d) && eq(a, c);
35  
  }
36  
  
37  
  bool usable() {
38  
    if (trivial()) ret false;
39  
    if (eq(a, 0) || eq(c, 0)) ret false;
40  
    if (eq(b, d)) ret false; // matchin kinds, non-matching numbers
41  
    ret true;
42  
  }
43  
}
44  
45  
static new L<NQ> terms;
46  
47  
p {
48  
  load(dataProgID, "terms");
49  
}
50  
51  
synchronized answer {
52  
  if (match("* * is * *", s, m) || match("* * are * *", s, m)) {
53  
    NQ nq = new NQ(m.unq(0), simplify(m.unq(1)), m.unq(2), simplify(m.unq(3)));
54  
    if (terms.contains(nq))
55  
      ret "I know!";
56  
    terms.add(nq);
57  
    save(dataProgID, "terms");
58  
    ret "OK, added to theory. Now " + l(terms) + " entries";
59  
  }
60  
  
61  
  if (match("show theory", s)) {
62  
    ret structure(allToString(terms));
63  
  }
64  
  
65  
  if (match("how many * * * *", s, m)) {
66  
    S isAre = m.get(1);
67  
    if (litlist("is", "are").contains(toLower(isAre))) {
68  
      BigInteger a = bigint(m.unq(2));
69  
      S b = m.unq(3);
70  
      S d = m.unq(0);
71  
      Rat c = calc(new Rat(a), b, d);
72  
      if (c == null)
73  
        ret "I don't know";
74  
      ret a + " " + b + " " + isAre + " " + c.mixed() + " " + d + "!";
75  
    }
76  
  }
77  
  
78  
  if (match("check theory", s))
79  
    ret checkTheory();
80  
    
81  
  if (match("show clusters", s))
82  
    ret showClusters();
83  
}
84  
85  
static Rat calc(Rat a, S b, S d) {
86  
  b = simplify(b);
87  
  d = simplify(d);
88  
  ret calcTransitive(a, b, d, new TreeSet);
89  
}
90  
91  
// b is the unit we have, d is the unit we're searching for
92  
static Rat calcTransitive(Rat a, S b, S d, Set<S> seen) {
93  
  print(format("calcTransitive * * * *", a, b, d, structure(seen)));
94  
  if (eq(b, d)) ret a; // done
95  
  if (seen.contains(b)) ret null;
96  
  seen.add(b);
97  
  for (NQ nq : terms) if (nq.usable()) {
98  
    twice {
99  
      if (eq(nq.b, b)) {
100  
        Rat r = calcTransitive(calcForward(nq, a), nq.d, d, seen);
101  
        if (r != null) ret r;
102  
      }
103  
      nq = nq.reverse();
104  
    }
105  
  }
106  
  null;
107  
}
108  
109  
static Rat calcForward(NQ nq, Rat a) {
110  
  ret a.multiply(nq.c).divide(nq.a);
111  
}
112  
113  
static S simplify(S s) {
114  
  ret toSingular(toLower(s));
115  
}
116  
117  
static S toSingular(S s) {
118  
  ret dropSuffix("s", s); // yeah it's rough
119  
}
120  
121  
static BigInteger smartBigint(S s) {
122  
  if (litlist("a", "an", "one").contains(toLower(s)))
123  
    ret bigint(1);
124  
  ret bigint(s);
125  
}
126  
127  
static S checkTheory() {
128  
  new L<NQ> trivial;
129  
  new L<NQ> valid;
130  
  new L<NQ> invalid;
131  
  for (NQ nq : terms) {
132  
    L<NQ> bucket = nq.trivial() ? trivial : nq.usable() ? valid : invalid;
133  
    bucket.add(nq);
134  
  }
135  
  
136  
  new StringBuilder buf;
137  
  if (!isEmpty(trivial))
138  
    buf.append(l(trivial) + " trivial: " + joinQuoted(", ", allToString(trivial)) + ".\n");
139  
  
140  
  if (!isEmpty(invalid))
141  
    buf.append(l(invalid) + " invalid: " + joinQuoted(", ", allToString(invalid)) + ".\n");
142  
  
143  
  if (!isEmpty(valid))
144  
    buf.append(l(valid) + " valid statements.\n");
145  
    
146  
  L<L<S>> clusters = getClusters();
147  
  buf.append(l(clusters) + " clusters. ");
148  
149  
  int consistent = 0;
150  
  new L<L<S>> inconsistent;
151  
  for (L<S> cluster : clusters) {
152  
    boolean ok = checkCluster(cluster);
153  
    if (ok) ++consistent; else inconsistent.add(cluster);
154  
  }
155  
  
156  
  if (isEmpty(inconsistent))
157  
    buf.append("All consistent.\n");
158  
  else {
159  
    buf.append(l(inconsistent) + " cluster(s) inconsistent:\n");
160  
    for (L<S> cluster : inconsistent)
161  
      buf.append("  " + structure(cluster) + "\n");
162  
  }
163  
164  
  ret trim(buf);
165  
}
166  
167  
static L<L<S>> getClusters() {
168  
  L<NQ> l = filterByMethod(terms, "usable"); // get all usable terms
169  
  
170  
  // a cluster is a list of concepts.
171  
  // first, make trivial clusters (one per concept).
172  
  
173  
  Map<S, L<S>> clusters = new TreeMap<S, L<S>>();
174  
  for (NQ nq : l) {
175  
    if (!clusters.containsKey(nq.b))
176  
      clusters.put(nq.b, litlist(nq.b));
177  
    if (!clusters.containsKey(nq.d))
178  
      clusters.put(nq.d, litlist(nq.d));
179  
  }
180  
  
181  
  // then, merge the clusters.
182  
  
183  
  for (NQ nq : l) {
184  
    L<S> c1 = clusters.get(nq.b), c2 = clusters.get(nq.d);
185  
    if (c1 != c2) { // different clusters, need to merge!
186  
      mergeClusters(clusters, c1, c2);
187  
    }
188  
  }
189  
  
190  
  // IdentitySet would be more efficient, but meh.
191  
  ret asList(new HashSet<L<S>>(clusters.values()));
192  
}
193  
194  
static S showClusters() {
195  
  L<L<S>> clusters = getClusters();
196  
  ret l(clusters) + " clusters: " + structure(clusters);
197  
}
198  
199  
static void mergeClusters(Map<S, L<S>> clusters, L<S> c1, L<S> c2) {
200  
  for (S concept : c2) {
201  
    clusters.put(concept, c1);
202  
    c1.add(concept);
203  
  }
204  
}
205  
206  
static boolean checkCluster(L<S> cluster) {
207  
  new Map<S, Rat> values;
208  
  
209  
  // randomly choose a concept and a value (!= 0) to start with
210  
  values.put(cluster.get(0), rat(1));
211  
  
212  
  while true {
213  
    int lastSize = l(values);
214  
    
215  
    for (NQ nq : terms) if (nq.usable()) {
216  
      twice {
217  
        Rat lvalue = values.get(nq.b);
218  
        if (lvalue != null) {
219  
          Rat rvalue = calcForward(nq, lvalue);
220  
          Rat expectedValue = values.get(nq.d);
221  
          if (expectedValue == null) 
222  
            values.put(nq.d, rvalue);
223  
          else if (neq(expectedValue, rvalue))
224  
            ret false; // Cluster is inconsistent!
225  
        }
226  
        nq = nq.reverse();
227  
      }
228  
    }
229  
    if (l(values) == lastSize) ret true; // all done
230  
  }
231  
}

Author comment

Began life as a copy of #1002049

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1002072
Snippet name: Conversion Bot (v2, LIVE)
Eternal ID of this version: #1002072/1
Text MD5: 37af9c21f669079c45890da4580c8ff5
Transpilation MD5: 449ebd0eb1bb2913c33d07c10efe6ffe
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-01-06 19:41:16
Source code size: 5812 bytes / 231 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 666 / 1878
Referenced in: [show references]