puzlink 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +35 -0
  3. package/dist/data/answerLengths.d.ts +10 -0
  4. package/dist/data/answerLengths.d.ts.map +1 -0
  5. package/dist/data/answerLengths.js +63 -0
  6. package/dist/data/answerLengths.js.map +1 -0
  7. package/dist/data/categories/compass.d.ts +3 -0
  8. package/dist/data/categories/compass.d.ts.map +1 -0
  9. package/dist/data/categories/compass.js +11 -0
  10. package/dist/data/categories/compass.js.map +1 -0
  11. package/dist/data/categories/countryAlpha2.d.ts +3 -0
  12. package/dist/data/categories/countryAlpha2.d.ts.map +1 -0
  13. package/dist/data/categories/countryAlpha2.js +252 -0
  14. package/dist/data/categories/countryAlpha2.js.map +1 -0
  15. package/dist/data/categories/countryAlpha3.d.ts +3 -0
  16. package/dist/data/categories/countryAlpha3.d.ts.map +1 -0
  17. package/dist/data/categories/countryAlpha3.js +252 -0
  18. package/dist/data/categories/countryAlpha3.js.map +1 -0
  19. package/dist/data/categories/daysOfTheWeek.d.ts +3 -0
  20. package/dist/data/categories/daysOfTheWeek.d.ts.map +1 -0
  21. package/dist/data/categories/daysOfTheWeek.js +10 -0
  22. package/dist/data/categories/daysOfTheWeek.js.map +1 -0
  23. package/dist/data/categories/elementSymbols.d.ts +3 -0
  24. package/dist/data/categories/elementSymbols.d.ts.map +1 -0
  25. package/dist/data/categories/elementSymbols.js +121 -0
  26. package/dist/data/categories/elementSymbols.js.map +1 -0
  27. package/dist/data/categories/greekLetters.d.ts +3 -0
  28. package/dist/data/categories/greekLetters.d.ts.map +1 -0
  29. package/dist/data/categories/greekLetters.js +27 -0
  30. package/dist/data/categories/greekLetters.js.map +1 -0
  31. package/dist/data/categories/months.d.ts +3 -0
  32. package/dist/data/categories/months.d.ts.map +1 -0
  33. package/dist/data/categories/months.js +15 -0
  34. package/dist/data/categories/months.js.map +1 -0
  35. package/dist/data/categories/natoAlphabet.d.ts +3 -0
  36. package/dist/data/categories/natoAlphabet.d.ts.map +1 -0
  37. package/dist/data/categories/natoAlphabet.js +29 -0
  38. package/dist/data/categories/natoAlphabet.js.map +1 -0
  39. package/dist/data/categories/numbers.d.ts +3 -0
  40. package/dist/data/categories/numbers.d.ts.map +1 -0
  41. package/dist/data/categories/numbers.js +16 -0
  42. package/dist/data/categories/numbers.js.map +1 -0
  43. package/dist/data/categories/romanNumerals.d.ts +3 -0
  44. package/dist/data/categories/romanNumerals.d.ts.map +1 -0
  45. package/dist/data/categories/romanNumerals.js +134 -0
  46. package/dist/data/categories/romanNumerals.js.map +1 -0
  47. package/dist/data/categories/solfege.d.ts +3 -0
  48. package/dist/data/categories/solfege.d.ts.map +1 -0
  49. package/dist/data/categories/solfege.js +11 -0
  50. package/dist/data/categories/solfege.js.map +1 -0
  51. package/dist/data/categories/usStateAbbreviations.d.ts +3 -0
  52. package/dist/data/categories/usStateAbbreviations.d.ts.map +1 -0
  53. package/dist/data/categories/usStateAbbreviations.js +53 -0
  54. package/dist/data/categories/usStateAbbreviations.js.map +1 -0
  55. package/dist/data/categories.d.ts +10 -0
  56. package/dist/data/categories.d.ts.map +1 -0
  57. package/dist/data/categories.js +31 -0
  58. package/dist/data/categories.js.map +1 -0
  59. package/dist/data/knownLogProbs.d.ts +6 -0
  60. package/dist/data/knownLogProbs.d.ts.map +1 -0
  61. package/dist/data/knownLogProbs.js +2975 -0
  62. package/dist/data/knownLogProbs.js.map +1 -0
  63. package/dist/data/morse.d.ts +2 -0
  64. package/dist/data/morse.d.ts.map +1 -0
  65. package/dist/data/morse.js +29 -0
  66. package/dist/data/morse.js.map +1 -0
  67. package/dist/data/scrabble.d.ts +2 -0
  68. package/dist/data/scrabble.d.ts.map +1 -0
  69. package/dist/data/scrabble.js +29 -0
  70. package/dist/data/scrabble.js.map +1 -0
  71. package/dist/features/index.d.ts +32 -0
  72. package/dist/features/index.d.ts.map +1 -0
  73. package/dist/features/index.js +79 -0
  74. package/dist/features/index.js.map +1 -0
  75. package/dist/features/letterCount.d.ts +7 -0
  76. package/dist/features/letterCount.d.ts.map +1 -0
  77. package/dist/features/letterCount.js +121 -0
  78. package/dist/features/letterCount.js.map +1 -0
  79. package/dist/features/letterSequence.d.ts +7 -0
  80. package/dist/features/letterSequence.d.ts.map +1 -0
  81. package/dist/features/letterSequence.js +155 -0
  82. package/dist/features/letterSequence.js.map +1 -0
  83. package/dist/features/logProbCache.d.ts +16 -0
  84. package/dist/features/logProbCache.d.ts.map +1 -0
  85. package/dist/features/logProbCache.js +36 -0
  86. package/dist/features/logProbCache.js.map +1 -0
  87. package/dist/features/other.d.ts +4 -0
  88. package/dist/features/other.d.ts.map +1 -0
  89. package/dist/features/other.js +190 -0
  90. package/dist/features/other.js.map +1 -0
  91. package/dist/features/substring.d.ts +3 -0
  92. package/dist/features/substring.d.ts.map +1 -0
  93. package/dist/features/substring.js +146 -0
  94. package/dist/features/substring.js.map +1 -0
  95. package/dist/features/wordplay.d.ts +7 -0
  96. package/dist/features/wordplay.d.ts.map +1 -0
  97. package/dist/features/wordplay.js +387 -0
  98. package/dist/features/wordplay.js.map +1 -0
  99. package/dist/index.d.ts +4 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +3 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/lib/affixDistribution.d.ts +26 -0
  104. package/dist/lib/affixDistribution.d.ts.map +1 -0
  105. package/dist/lib/affixDistribution.js +105 -0
  106. package/dist/lib/affixDistribution.js.map +1 -0
  107. package/dist/lib/counter.d.ts +23 -0
  108. package/dist/lib/counter.d.ts.map +1 -0
  109. package/dist/lib/counter.js +55 -0
  110. package/dist/lib/counter.js.map +1 -0
  111. package/dist/lib/distribution.d.ts +40 -0
  112. package/dist/lib/distribution.d.ts.map +1 -0
  113. package/dist/lib/distribution.js +176 -0
  114. package/dist/lib/distribution.js.map +1 -0
  115. package/dist/lib/lengthDistribution.d.ts +30 -0
  116. package/dist/lib/lengthDistribution.d.ts.map +1 -0
  117. package/dist/lib/lengthDistribution.js +137 -0
  118. package/dist/lib/lengthDistribution.js.map +1 -0
  119. package/dist/lib/letterBitset.d.ts +49 -0
  120. package/dist/lib/letterBitset.d.ts.map +1 -0
  121. package/dist/lib/letterBitset.js +101 -0
  122. package/dist/lib/letterBitset.js.map +1 -0
  123. package/dist/lib/letterDistribution.d.ts +60 -0
  124. package/dist/lib/letterDistribution.d.ts.map +1 -0
  125. package/dist/lib/letterDistribution.js +230 -0
  126. package/dist/lib/letterDistribution.js.map +1 -0
  127. package/dist/lib/letterIndices.d.ts +13 -0
  128. package/dist/lib/letterIndices.d.ts.map +1 -0
  129. package/dist/lib/letterIndices.js +41 -0
  130. package/dist/lib/letterIndices.js.map +1 -0
  131. package/dist/lib/logCounter.d.ts +23 -0
  132. package/dist/lib/logCounter.d.ts.map +1 -0
  133. package/dist/lib/logCounter.js +49 -0
  134. package/dist/lib/logCounter.js.map +1 -0
  135. package/dist/lib/logNum.d.ts +36 -0
  136. package/dist/lib/logNum.d.ts.map +1 -0
  137. package/dist/lib/logNum.js +193 -0
  138. package/dist/lib/logNum.js.map +1 -0
  139. package/dist/lib/memoize.d.ts +5 -0
  140. package/dist/lib/memoize.d.ts.map +1 -0
  141. package/dist/lib/memoize.js +104 -0
  142. package/dist/lib/memoize.js.map +1 -0
  143. package/dist/lib/util.d.ts +30 -0
  144. package/dist/lib/util.d.ts.map +1 -0
  145. package/dist/lib/util.js +111 -0
  146. package/dist/lib/util.js.map +1 -0
  147. package/dist/lib/wordlist.d.ts +66 -0
  148. package/dist/lib/wordlist.d.ts.map +1 -0
  149. package/dist/lib/wordlist.js +166 -0
  150. package/dist/lib/wordlist.js.map +1 -0
  151. package/dist/linkers/index.d.ts +34 -0
  152. package/dist/linkers/index.d.ts.map +1 -0
  153. package/dist/linkers/index.js +25 -0
  154. package/dist/linkers/index.js.map +1 -0
  155. package/dist/linkers/indexing.d.ts +5 -0
  156. package/dist/linkers/indexing.d.ts.map +1 -0
  157. package/dist/linkers/indexing.js +152 -0
  158. package/dist/linkers/indexing.js.map +1 -0
  159. package/dist/linkers/length.d.ts +5 -0
  160. package/dist/linkers/length.d.ts.map +1 -0
  161. package/dist/linkers/length.js +101 -0
  162. package/dist/linkers/length.js.map +1 -0
  163. package/dist/linkers/letterDistribution.d.ts +4 -0
  164. package/dist/linkers/letterDistribution.d.ts.map +1 -0
  165. package/dist/linkers/letterDistribution.js +46 -0
  166. package/dist/linkers/letterDistribution.js.map +1 -0
  167. package/dist/linkers/other.d.ts +5 -0
  168. package/dist/linkers/other.d.ts.map +1 -0
  169. package/dist/linkers/other.js +90 -0
  170. package/dist/linkers/other.js.map +1 -0
  171. package/dist/parse.d.ts +8 -0
  172. package/dist/parse.d.ts.map +1 -0
  173. package/dist/parse.js +23 -0
  174. package/dist/parse.js.map +1 -0
  175. package/dist/puzlink.d.ts +84 -0
  176. package/dist/puzlink.d.ts.map +1 -0
  177. package/dist/puzlink.js +59 -0
  178. package/dist/puzlink.js.map +1 -0
  179. package/package.json +57 -0
  180. package/src/data/answerLengths.ts +63 -0
  181. package/src/data/categories/README.md +3 -0
  182. package/src/data/categories/compass.ts +1 -0
  183. package/src/data/categories/countryAlpha2.ts +251 -0
  184. package/src/data/categories/countryAlpha3.ts +251 -0
  185. package/src/data/categories/daysOfTheWeek.ts +1 -0
  186. package/src/data/categories/elementSymbols.ts +120 -0
  187. package/src/data/categories/greekLetters.ts +26 -0
  188. package/src/data/categories/months.ts +14 -0
  189. package/src/data/categories/natoAlphabet.ts +28 -0
  190. package/src/data/categories/numbers.ts +15 -0
  191. package/src/data/categories/romanNumerals.ts +133 -0
  192. package/src/data/categories/solfege.ts +1 -0
  193. package/src/data/categories/txt/compass.txt +8 -0
  194. package/src/data/categories/txt/daysOfTheWeek.txt +7 -0
  195. package/src/data/categories/txt/elementSymbols.txt +118 -0
  196. package/src/data/categories/txt/greekLetters.txt +24 -0
  197. package/src/data/categories/txt/months.txt +12 -0
  198. package/src/data/categories/txt/natoAlphabet.txt +26 -0
  199. package/src/data/categories/txt/numbers.txt +13 -0
  200. package/src/data/categories/txt/solfege.txt +8 -0
  201. package/src/data/categories/txt/usStateAbbreviations.txt +50 -0
  202. package/src/data/categories/usStateAbbreviations.ts +52 -0
  203. package/src/data/categories.ts +42 -0
  204. package/src/data/knownLogProbs.ts +2992 -0
  205. package/src/data/morse.ts +28 -0
  206. package/src/data/scrabble.ts +28 -0
  207. package/src/features/index.ts +120 -0
  208. package/src/features/letterCount.ts +174 -0
  209. package/src/features/letterSequence.ts +222 -0
  210. package/src/features/logProbCache.ts +48 -0
  211. package/src/features/other.ts +214 -0
  212. package/src/features/substring.ts +173 -0
  213. package/src/features/wordplay.ts +428 -0
  214. package/src/index.ts +3 -0
  215. package/src/lib/affixDistribution.ts +70 -0
  216. package/src/lib/counter.ts +71 -0
  217. package/src/lib/distribution.ts +162 -0
  218. package/src/lib/lengthDistribution.ts +108 -0
  219. package/src/lib/letterBitset.ts +123 -0
  220. package/src/lib/letterDistribution.ts +236 -0
  221. package/src/lib/letterIndices.ts +51 -0
  222. package/src/lib/logCounter.ts +74 -0
  223. package/src/lib/logNum.ts +193 -0
  224. package/src/lib/memoize.ts +136 -0
  225. package/src/lib/testUtils.ts +1 -0
  226. package/src/lib/util.ts +150 -0
  227. package/src/lib/wordlist.ts +162 -0
  228. package/src/linkers/index.ts +56 -0
  229. package/src/linkers/indexing.ts +194 -0
  230. package/src/linkers/length.ts +122 -0
  231. package/src/linkers/other.ts +117 -0
  232. package/src/parse.ts +20 -0
  233. package/src/puzlink.ts +141 -0
@@ -0,0 +1,40 @@
1
+ import { LogCounter } from "./logCounter.js";
2
+ import { LogNum } from "./logNum.js";
3
+ /** A probability distribution of items. */
4
+ export declare class Distribution<T extends PropertyKey> {
5
+ private readonly frequencies;
6
+ constructor(frequencies: ReadonlyMap<T, LogNum>);
7
+ static from(data: string): Distribution<string>;
8
+ static from<T extends PropertyKey>(data: readonly T[]): Distribution<T>;
9
+ static from<T extends PropertyKey>(counter: LogCounter<T>): Distribution<T>;
10
+ /** Get the frequency of the given item. */
11
+ get(item: T): LogNum;
12
+ /** Returns an iterable of [item, log probability] pairs. */
13
+ entries(): IterableIterator<[T, LogNum]>;
14
+ /** k-th moment of the distribution. */
15
+ moment(k: number): LogNum;
16
+ /** Log probability that k items drawn from the distribution are all equal. */
17
+ probEqual(k: number): LogNum;
18
+ /**
19
+ * Log probability that k items drawn from the distribution have two distinct
20
+ * values.
21
+ */
22
+ probTwoDistinct(k: number): LogNum;
23
+ /**
24
+ * Log probability that k items drawn from the distribution are all equal,
25
+ * with exactly one exception.
26
+ */
27
+ probAlmostEqual(k: number): LogNum;
28
+ /** Map the items of the distribution, returning the new distribution. */
29
+ map<U extends PropertyKey>(fn: (item: T) => U): Distribution<U>;
30
+ /** Chi-squared test statistic against an observed distribution. */
31
+ chi2(observed: LogCounter<T>): LogNum;
32
+ /** Log probability that an unordered distribution is drawn from this. */
33
+ probUnordered(observed: LogCounter<T>): LogNum;
34
+ /** Over- and under-represented items, at the given sigma. */
35
+ outliers(observed: LogCounter<T>, sigma?: number): {
36
+ high: Record<T, LogNum>;
37
+ low: Record<T, LogNum>;
38
+ };
39
+ }
40
+ //# sourceMappingURL=distribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distribution.d.ts","sourceRoot":"","sources":["../../src/lib/distribution.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,2CAA2C;AAC3C,qBAAa,YAAY,CAAC,CAAC,SAAS,WAAW;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;gBAEzC,WAAW,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC;IAI/C,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;IAC/C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAO3E,2CAA2C;IAC3C,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM;IAIpB,4DAA4D;IAC5D,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAIxC,uCAAuC;IAEvC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAMzB,8EAA8E;IAC9E,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAO5B;;;OAGG;IAEH,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAclC;;;OAGG;IAEH,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAalC,yEAAyE;IACzE,GAAG,CAAC,CAAC,SAAS,WAAW,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAY/D,mEAAmE;IACnE,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM;IAkBrC,yEAAyE;IACzE,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM;IAM9C,6DAA6D;IAC7D,QAAQ,CACN,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,EACvB,KAAK,SAAI,GACR;QACD,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;KACxB;CA6BF"}
@@ -0,0 +1,176 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { cumulativeStdNormalProbability as normCdf } from "simple-statistics";
36
+ import { LogCounter } from "./logCounter.js";
37
+ import { LogNum } from "./logNum.js";
38
+ import { memoize } from "./memoize.js";
39
+ import { interval } from "./util.js";
40
+ /** A probability distribution of items. */
41
+ let Distribution = (() => {
42
+ let _instanceExtraInitializers = [];
43
+ let _moment_decorators;
44
+ let _probTwoDistinct_decorators;
45
+ let _probAlmostEqual_decorators;
46
+ return class Distribution {
47
+ static {
48
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
49
+ _moment_decorators = [memoize()];
50
+ _probTwoDistinct_decorators = [memoize()];
51
+ _probAlmostEqual_decorators = [memoize()];
52
+ __esDecorate(this, null, _moment_decorators, { kind: "method", name: "moment", static: false, private: false, access: { has: obj => "moment" in obj, get: obj => obj.moment }, metadata: _metadata }, null, _instanceExtraInitializers);
53
+ __esDecorate(this, null, _probTwoDistinct_decorators, { kind: "method", name: "probTwoDistinct", static: false, private: false, access: { has: obj => "probTwoDistinct" in obj, get: obj => obj.probTwoDistinct }, metadata: _metadata }, null, _instanceExtraInitializers);
54
+ __esDecorate(this, null, _probAlmostEqual_decorators, { kind: "method", name: "probAlmostEqual", static: false, private: false, access: { has: obj => "probAlmostEqual" in obj, get: obj => obj.probAlmostEqual }, metadata: _metadata }, null, _instanceExtraInitializers);
55
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
56
+ }
57
+ frequencies = __runInitializers(this, _instanceExtraInitializers);
58
+ constructor(frequencies) {
59
+ this.frequencies = frequencies;
60
+ }
61
+ static from(data) {
62
+ const counter = data instanceof LogCounter ? data : LogCounter.from(data);
63
+ return new Distribution(new Map(counter.frequencies()));
64
+ }
65
+ /** Get the frequency of the given item. */
66
+ get(item) {
67
+ return this.frequencies.get(item) ?? LogNum.from(0);
68
+ }
69
+ /** Returns an iterable of [item, log probability] pairs. */
70
+ entries() {
71
+ return this.frequencies.entries();
72
+ }
73
+ /** k-th moment of the distribution. */
74
+ moment(k) {
75
+ return LogNum.sum(Array.from(this.frequencies.values(), (freq) => freq.pow(k)));
76
+ }
77
+ /** Log probability that k items drawn from the distribution are all equal. */
78
+ probEqual(k) {
79
+ if (k <= 0) {
80
+ return LogNum.from(1);
81
+ }
82
+ return this.moment(k);
83
+ }
84
+ /**
85
+ * Log probability that k items drawn from the distribution have two distinct
86
+ * values.
87
+ */
88
+ probTwoDistinct(k) {
89
+ const probs = [];
90
+ for (const i of interval(0, k)) {
91
+ const j = k - i;
92
+ probs.push(LogNum.fromBinomial(k, i).mul(this.probEqual(i)).mul(this.probEqual(j)));
93
+ }
94
+ // Case where all are equal is counted 2^k times; others are counted twice:
95
+ return LogNum.sum(probs)
96
+ .sub(LogNum.from(2).pow(k).mul(this.probEqual(k)))
97
+ .div(LogNum.from(2));
98
+ }
99
+ /**
100
+ * Log probability that k items drawn from the distribution are all equal,
101
+ * with exactly one exception.
102
+ */
103
+ probAlmostEqual(k) {
104
+ const probs = [];
105
+ for (const [, freq] of this.frequencies) {
106
+ probs.push(this.moment(k - 1)
107
+ .sub(freq.pow(k - 1))
108
+ .mul(freq)
109
+ .mul(LogNum.from(k)));
110
+ }
111
+ return LogNum.sum(probs);
112
+ }
113
+ /** Map the items of the distribution, returning the new distribution. */
114
+ map(fn) {
115
+ const frequencies = new Map();
116
+ for (const [item, freq] of this.frequencies) {
117
+ const mapped = fn(item);
118
+ frequencies.set(mapped, (frequencies.get(mapped) ?? LogNum.from(0)).add(freq));
119
+ }
120
+ return new Distribution(frequencies);
121
+ }
122
+ /** Chi-squared test statistic against an observed distribution. */
123
+ chi2(observed) {
124
+ for (const [item] of observed.entries()) {
125
+ if (!this.frequencies.has(item)) {
126
+ return LogNum.from(Infinity);
127
+ }
128
+ }
129
+ const n = observed.total;
130
+ const partials = [];
131
+ for (const [item, freq] of this.frequencies) {
132
+ const expected = n.mul(freq);
133
+ const actual = observed.get(item);
134
+ // Under chi-squared assumptions, the (expected - actual)^2/expected
135
+ // should be iid N(0, 1)^2.
136
+ partials.push(expected.absSub(actual).pow(2).div(expected));
137
+ }
138
+ return LogNum.sum(partials);
139
+ }
140
+ /** Log probability that an unordered distribution is drawn from this. */
141
+ probUnordered(observed) {
142
+ const df = this.frequencies.size - 1;
143
+ const z = (this.chi2(observed).toNum() - df) / Math.sqrt(2 * df);
144
+ return LogNum.from(1 - normCdf(z));
145
+ }
146
+ /** Over- and under-represented items, at the given sigma. */
147
+ outliers(observed, sigma = 2) {
148
+ const n = observed.total;
149
+ const low = {};
150
+ const high = {};
151
+ const keys = [
152
+ ...this.frequencies.keys(),
153
+ ...observed.filterKeys((key) => !this.frequencies.has(key)),
154
+ ];
155
+ const threshold = LogNum.from(sigma ** 2);
156
+ for (const item of keys) {
157
+ const freq = this.frequencies.get(item) ?? LogNum.from(0);
158
+ const expected = n.mul(freq);
159
+ const actual = observed.get(item);
160
+ // We assume (expected - actual)^2/expected should be distributed as
161
+ // N(0, 1)^2; thus if it's over sigma^2, it's an outlier.
162
+ if (expected.absSub(actual).pow(2).div(expected).gt(threshold)) {
163
+ if (expected.gt(actual)) {
164
+ low[item] = expected.sub(actual);
165
+ }
166
+ else {
167
+ high[item] = actual.sub(expected);
168
+ }
169
+ }
170
+ }
171
+ return { high, low };
172
+ }
173
+ };
174
+ })();
175
+ export { Distribution };
176
+ //# sourceMappingURL=distribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distribution.js","sourceRoot":"","sources":["../../src/lib/distribution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { Distribution } from "./distribution.js";
2
+ import { LogNum } from "./logNum.js";
3
+ export declare class LengthDistribution {
4
+ readonly distribution: Distribution<number>;
5
+ private readonly distMod2;
6
+ private readonly distMod3;
7
+ /** Length such that 99.9% of answers have length less than this. */
8
+ private readonly maxLength;
9
+ constructor(distribution: Distribution<number>);
10
+ static from(data: Map<number, LogNum>): LengthDistribution;
11
+ /** Log probability that k words have the same length. */
12
+ probEqual(k: number): LogNum;
13
+ /** Log probability that k words have the same length, except for one. */
14
+ probAlmostEqual(k: number): LogNum;
15
+ /** Log probability that k words have the same length modulo 2. */
16
+ probEqualMod2(k: number): LogNum;
17
+ /** Log probability that k words have the same length modulo 3. */
18
+ probEqualMod3(k: number): LogNum;
19
+ /** Log probability that k words have consecutive lengths. */
20
+ probConsecutive(k: number): LogNum;
21
+ /** Log probability that k words have exactly two distinct lengths. */
22
+ probTwoDistinct(k: number): LogNum;
23
+ /**
24
+ * Log probability that k words have distinct lengths, all at least min.
25
+ */
26
+ probDistinct(k: number, min?: number): LogNum;
27
+ /** Log probability that k words can be paired by length. */
28
+ probPaired(k: number): LogNum;
29
+ }
30
+ //# sourceMappingURL=lengthDistribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lengthDistribution.d.ts","sourceRoot":"","sources":["../../src/lib/lengthDistribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuB;IAChD,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC;IAgB9C,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,kBAAkB;IAI1D,yDAAyD;IACzD,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI5B,yEAAyE;IACzE,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIlC,kEAAkE;IAClE,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIhC,kEAAkE;IAClE,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIhC,6DAA6D;IAE7D,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAiBlC,sEAAsE;IACtE,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIlC;;OAEG;IAEH,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,MAAM;IAoBxC,4DAA4D;IAC5D,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;CAM9B"}
@@ -0,0 +1,137 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { Distribution } from "./distribution.js";
36
+ import { LogNum } from "./logNum.js";
37
+ import { memoize } from "./memoize.js";
38
+ import { interval, windows } from "./util.js";
39
+ let LengthDistribution = (() => {
40
+ let _instanceExtraInitializers = [];
41
+ let _probConsecutive_decorators;
42
+ let _probDistinct_decorators;
43
+ return class LengthDistribution {
44
+ static {
45
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
46
+ _probConsecutive_decorators = [memoize()];
47
+ _probDistinct_decorators = [memoize(2)];
48
+ __esDecorate(this, null, _probConsecutive_decorators, { kind: "method", name: "probConsecutive", static: false, private: false, access: { has: obj => "probConsecutive" in obj, get: obj => obj.probConsecutive }, metadata: _metadata }, null, _instanceExtraInitializers);
49
+ __esDecorate(this, null, _probDistinct_decorators, { kind: "method", name: "probDistinct", static: false, private: false, access: { has: obj => "probDistinct" in obj, get: obj => obj.probDistinct }, metadata: _metadata }, null, _instanceExtraInitializers);
50
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
51
+ }
52
+ distribution = __runInitializers(this, _instanceExtraInitializers);
53
+ distMod2;
54
+ distMod3;
55
+ /** Length such that 99.9% of answers have length less than this. */
56
+ maxLength;
57
+ constructor(distribution) {
58
+ this.distribution = distribution;
59
+ this.distMod2 = this.distribution.map((length) => length % 2);
60
+ this.distMod3 = this.distribution.map((length) => length % 3);
61
+ this.maxLength = Infinity;
62
+ let totalProb = LogNum.from(0);
63
+ for (const [length, freq] of distribution.entries()) {
64
+ totalProb = totalProb.add(freq);
65
+ if (totalProb.gt(LogNum.from(0.999))) {
66
+ this.maxLength = length;
67
+ break;
68
+ }
69
+ }
70
+ }
71
+ static from(data) {
72
+ return new LengthDistribution(new Distribution(data));
73
+ }
74
+ /** Log probability that k words have the same length. */
75
+ probEqual(k) {
76
+ return this.distribution.probEqual(k);
77
+ }
78
+ /** Log probability that k words have the same length, except for one. */
79
+ probAlmostEqual(k) {
80
+ return this.distribution.probAlmostEqual(k);
81
+ }
82
+ /** Log probability that k words have the same length modulo 2. */
83
+ probEqualMod2(k) {
84
+ return this.distMod2.probEqual(k);
85
+ }
86
+ /** Log probability that k words have the same length modulo 3. */
87
+ probEqualMod3(k) {
88
+ return this.distMod3.probEqual(k);
89
+ }
90
+ /** Log probability that k words have consecutive lengths. */
91
+ probConsecutive(k) {
92
+ if (k <= 1) {
93
+ return LogNum.from(1);
94
+ }
95
+ else if (k > this.maxLength) {
96
+ return LogNum.from(0);
97
+ }
98
+ const range = interval(1, this.maxLength).map((i) => this.distribution.get(i));
99
+ const partials = Array.from(windows(range, k), (window) => LogNum.prod(window));
100
+ return LogNum.fromFactorial(k).mul(LogNum.sum(partials));
101
+ }
102
+ /** Log probability that k words have exactly two distinct lengths. */
103
+ probTwoDistinct(k) {
104
+ return this.distribution.probTwoDistinct(k);
105
+ }
106
+ /**
107
+ * Log probability that k words have distinct lengths, all at least min.
108
+ */
109
+ probDistinct(k, min = 0) {
110
+ if (k <= 0) {
111
+ return LogNum.from(1);
112
+ }
113
+ else if (min > this.maxLength) {
114
+ return LogNum.from(0);
115
+ }
116
+ const probs = [];
117
+ for (const [length, freq] of this.distribution.entries()) {
118
+ if (length < min) {
119
+ continue;
120
+ }
121
+ probs.push(freq.mul(this.probDistinct(k - 1, length + 1)));
122
+ }
123
+ return probs.length === 0
124
+ ? LogNum.from(0)
125
+ : LogNum.from(k).mul(LogNum.sum(probs));
126
+ }
127
+ /** Log probability that k words can be paired by length. */
128
+ probPaired(k) {
129
+ if (k % 2 !== 0) {
130
+ return LogNum.from(0);
131
+ }
132
+ return this.probDistinct(Math.floor(k / 2));
133
+ }
134
+ };
135
+ })();
136
+ export { LengthDistribution };
137
+ //# sourceMappingURL=lengthDistribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lengthDistribution.js","sourceRoot":"","sources":["../../src/lib/lengthDistribution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * A class that uses a single bigint to store counts for each lowercase letter,
3
+ * for fast-ish comparison.
4
+ *
5
+ * Idea stolen from Collective.jl:
6
+ * https://github.com/rdeits/Collective.jl/blob/master/src/bitstally.jl
7
+ */
8
+ export declare class LetterBitset {
9
+ private static readonly bits;
10
+ private static readonly mask;
11
+ private static readonly offsets;
12
+ private static readonly letterMasks;
13
+ /**
14
+ * This is a (26 * 5)-bit integer; each 5-bit block is a count for a letter.
15
+ * Unclear how efficient this'll be for different engines...
16
+ *
17
+ * Note that 26 * 5 = 130, so these *mostly* fit in 128-bit integers, unless
18
+ * there's more than 7 'z's.
19
+ */
20
+ readonly data: bigint;
21
+ constructor(data: bigint);
22
+ private static toIndex;
23
+ private static fromIndex;
24
+ /** Create a new LetterCounter from a slug. */
25
+ static from(slug: string): LetterBitset;
26
+ /** Count the number of times the given letter appears in this bitset. */
27
+ index(letter: string): number;
28
+ equals(other: LetterBitset): boolean;
29
+ add(char: string): LetterBitset;
30
+ sub(char: string): LetterBitset;
31
+ /** If this + result == other, return result; else null. */
32
+ transaddOf(other: LetterBitset): string | null;
33
+ /** If this - result == other, return result; else null. */
34
+ transdeleteOf(other: LetterBitset): string | null;
35
+ }
36
+ /** A map from letter bitsets to words with that bitset. */
37
+ export declare class LetterBitsets {
38
+ private letterCounters;
39
+ private lengths;
40
+ constructor(wordlist: string[]);
41
+ /** Get the words whose bitset matches the given slug's bitset. */
42
+ get(slug: string): string[];
43
+ /** Find all substrings of the slug that anagram to a word's bitset. */
44
+ matchSubstring(slug: string): Generator<{
45
+ start: number;
46
+ words: string[];
47
+ }>;
48
+ }
49
+ //# sourceMappingURL=letterBitset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letterBitset.d.ts","sourceRoot":"","sources":["../../src/lib/letterBitset.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAM;IAClC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAkC;IAC9D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAEiB;IAChD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAEjC;IAEF;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM;IAIxB,OAAO,CAAC,MAAM,CAAC,OAAO;IAItB,OAAO,CAAC,MAAM,CAAC,SAAS;IAIxB,8CAA8C;IAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM;IAQxB,yEAAyE;IACzE,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAO7B,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAIpC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAM/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAM/B,2DAA2D;IAC3D,UAAU,CAAC,KAAK,EAAE,YAAY;IAS9B,2DAA2D;IAC3D,aAAa,CAAC,KAAK,EAAE,YAAY;CAGlC;AAED,2DAA2D;AAC3D,qBAAa,aAAa;IACxB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,OAAO,CAAqB;gBAExB,QAAQ,EAAE,MAAM,EAAE;IAW9B,kEAAkE;IAClE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAI3B,uEAAuE;IACtE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAa7E"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * A class that uses a single bigint to store counts for each lowercase letter,
3
+ * for fast-ish comparison.
4
+ *
5
+ * Idea stolen from Collective.jl:
6
+ * https://github.com/rdeits/Collective.jl/blob/master/src/bitstally.jl
7
+ */
8
+ export class LetterBitset {
9
+ static bits = 5n;
10
+ static mask = (1n << LetterBitset.bits) - 1n;
11
+ static offsets = Array(26)
12
+ .fill(0)
13
+ .map((_, i) => LetterBitset.bits * BigInt(i));
14
+ static letterMasks = LetterBitset.offsets.map((x) => 1n << x);
15
+ /**
16
+ * This is a (26 * 5)-bit integer; each 5-bit block is a count for a letter.
17
+ * Unclear how efficient this'll be for different engines...
18
+ *
19
+ * Note that 26 * 5 = 130, so these *mostly* fit in 128-bit integers, unless
20
+ * there's more than 7 'z's.
21
+ */
22
+ data;
23
+ constructor(data) {
24
+ this.data = data;
25
+ }
26
+ static toIndex(letter) {
27
+ return letter.charCodeAt(0) - 97;
28
+ }
29
+ static fromIndex(index) {
30
+ return String.fromCharCode(97 + index);
31
+ }
32
+ /** Create a new LetterCounter from a slug. */
33
+ static from(slug) {
34
+ let data = 0n;
35
+ for (const char of slug) {
36
+ data += LetterBitset.letterMasks[this.toIndex(char)];
37
+ }
38
+ return new LetterBitset(data);
39
+ }
40
+ /** Count the number of times the given letter appears in this bitset. */
41
+ index(letter) {
42
+ return Number((this.data >> LetterBitset.offsets[LetterBitset.toIndex(letter)]) &
43
+ LetterBitset.mask);
44
+ }
45
+ equals(other) {
46
+ return this.data === other.data;
47
+ }
48
+ add(char) {
49
+ return new LetterBitset(this.data + (LetterBitset.letterMasks[LetterBitset.toIndex(char)] ?? 0n));
50
+ }
51
+ sub(char) {
52
+ return new LetterBitset(this.data - (LetterBitset.letterMasks[LetterBitset.toIndex(char)] ?? 0n));
53
+ }
54
+ /** If this + result == other, return result; else null. */
55
+ transaddOf(other) {
56
+ const diff = this.data - other.data;
57
+ const index = LetterBitset.letterMasks.findIndex((mask) => diff === mask);
58
+ if (index === -1) {
59
+ return null;
60
+ }
61
+ return LetterBitset.fromIndex(index);
62
+ }
63
+ /** If this - result == other, return result; else null. */
64
+ transdeleteOf(other) {
65
+ return other.transaddOf(this);
66
+ }
67
+ }
68
+ /** A map from letter bitsets to words with that bitset. */
69
+ export class LetterBitsets {
70
+ letterCounters = new Map();
71
+ lengths = new Set();
72
+ constructor(wordlist) {
73
+ for (const word of wordlist) {
74
+ const bitset = LetterBitset.from(word).data;
75
+ if (!this.letterCounters.has(bitset)) {
76
+ this.letterCounters.set(bitset, []);
77
+ }
78
+ this.letterCounters.get(bitset).push(word);
79
+ this.lengths.add(word.length);
80
+ }
81
+ }
82
+ /** Get the words whose bitset matches the given slug's bitset. */
83
+ get(slug) {
84
+ return this.letterCounters.get(LetterBitset.from(slug).data) ?? [];
85
+ }
86
+ /** Find all substrings of the slug that anagram to a word's bitset. */
87
+ *matchSubstring(slug) {
88
+ for (const length of this.lengths) {
89
+ let start = 0;
90
+ let bitset = LetterBitset.from(slug.slice(0, length));
91
+ for (; start + length <= slug.length; start++) {
92
+ const words = this.letterCounters.get(bitset.data);
93
+ if (words && words.length > 0) {
94
+ yield { start, words };
95
+ }
96
+ bitset = bitset.sub(slug[start] ?? "").add(slug[start + length] ?? "");
97
+ }
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=letterBitset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letterBitset.js","sourceRoot":"","sources":["../../src/lib/letterBitset.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IACf,MAAM,CAAU,IAAI,GAAG,EAAE,CAAC;IAC1B,MAAM,CAAU,IAAI,GAAG,CAAC,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACtD,MAAM,CAAU,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC;SACxC,IAAI,CAAC,CAAC,CAAC;SACP,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,CAAU,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAC5D,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CACf,CAAC;IAEF;;;;;;OAMG;IACM,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAEO,MAAM,CAAC,OAAO,CAAC,MAAc;QACnC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACnC,CAAC;IAEO,MAAM,CAAC,SAAS,CAAC,KAAa;QACpC,OAAO,MAAM,CAAC,YAAY,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,8CAA8C;IAC9C,MAAM,CAAC,IAAI,CAAC,IAAY;QACtB,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAE,CAAC;QACxD,CAAC;QACD,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,MAAc;QAClB,OAAO,MAAM,CACX,CAAC,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAE,CAAC;YAChE,YAAY,CAAC,IAAI,CACpB,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAmB;QACxB,OAAO,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC;IAClC,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,YAAY,CACrB,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CACzE,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,YAAY,CACrB,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CACzE,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,UAAU,CAAC,KAAmB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACpC,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC1E,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,2DAA2D;IAC3D,aAAa,CAAC,KAAmB;QAC/B,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;;AAGH,2DAA2D;AAC3D,MAAM,OAAO,aAAa;IAChB,cAAc,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,YAAY,QAAkB;QAC5B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrE,CAAC;IAED,uEAAuE;IACvE,CAAC,cAAc,CAAC,IAAY;QAC1B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACtD,OAAO,KAAK,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACnD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;gBACzB,CAAC;gBACD,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,60 @@
1
+ import { Distribution } from "./distribution.js";
2
+ import { LogNum } from "./logNum.js";
3
+ export declare const LETTERS = "abcdefghijklmnopqrstuvwxyz";
4
+ export declare const VOWELS = "aeiou";
5
+ export declare const CONSONANTS = "bcdfghjklmnpqrstvwxyz";
6
+ /**
7
+ * Info about the letter distribution of a wordlist.
8
+ *
9
+ * All of these methods rely on letters being drawn iid. This is the case for
10
+ * letters that come from random indexing. This is *not* the case for things
11
+ * like random substrings.
12
+ */
13
+ export declare class LetterDistribution {
14
+ readonly distribution: Distribution<string>;
15
+ private readonly lengthToProbs;
16
+ constructor(wordlist: string[]);
17
+ /**
18
+ * Log probability that a list of letters is iid drawn from this distribution,
19
+ * via chi-squared.
20
+ */
21
+ probUnordered(letters: string[]): LogNum;
22
+ /** Over- and under-represented letters, at 2 sigma. */
23
+ outliers(letters: string[]): {
24
+ high: string[];
25
+ low: string[];
26
+ };
27
+ /**
28
+ * Log probability that words of given lengths share common letters, in the
29
+ * same order.
30
+ */
31
+ probCommonOrdered(common: number, lengths: number[]): LogNum;
32
+ /** Log probability that k letters are all equal. */
33
+ probEqual(k: number): LogNum;
34
+ /** Log probability that k letters are all equal, except for one. */
35
+ probAlmostEqual(k: number): LogNum;
36
+ /** Log probability that k letters have exactly two values. */
37
+ probTwoDistinct(k: number): LogNum;
38
+ /** Log probability that k letters are consecutive. */
39
+ probConsecutive(k: number): LogNum;
40
+ /**
41
+ * Log probability that k letters have distinct values, all at least min.
42
+ */
43
+ probDistinct(k: number, min?: string): LogNum;
44
+ /** Log probability that k letters can be grouped in equal pairs. */
45
+ probPaired(k: number): LogNum;
46
+ /** Log probability that k letters form a word. */
47
+ probWord(k: number): LogNum;
48
+ /** Log probability that k letters form an anagram of a word. */
49
+ probAnagram(k: number): LogNum;
50
+ /** Log probability that k letters are all vowels. */
51
+ probVowels(k: number): LogNum;
52
+ /** Log probability that k letters are all consonants. */
53
+ probConsonants(k: number): LogNum;
54
+ /**
55
+ * Log probability that n words, each of length k, have the same pattern of
56
+ * vowels and consonants.
57
+ */
58
+ probEqualVowelPattern(n: number, k: number): LogNum;
59
+ }
60
+ //# sourceMappingURL=letterDistribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letterDistribution.d.ts","sourceRoot":"","sources":["../../src/lib/letterDistribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,eAAO,MAAM,UAAU,0BAA0B,CAAC;AAElD;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAC7B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAQ5B;gBAEU,QAAQ,EAAE,MAAM,EAAE;IAoD9B;;;OAGG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM;IAKxC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;QAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,GAAG,EAAE,MAAM,EAAE,CAAC;KACf;IAMD;;;OAGG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM;IAe5D,oDAAoD;IACpD,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI5B,oEAAoE;IACpE,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIlC,8DAA8D;IAC9D,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIlC,sDAAsD;IAEtD,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAsBlC;;OAEG;IAEH,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM;IAoB1C,oEAAoE;IACpE,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAO7B,kDAAkD;IAClD,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI3B,gEAAgE;IAChE,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAI9B,qDAAqD;IAErD,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAY7B,yDAAyD;IAEzD,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAYjC;;;OAGG;IACH,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAGpD"}