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,152 @@
1
+ import { LetterIndices } from "../lib/letterIndices.js";
2
+ import { getArithmeticSequenceInfo, interval, ordinal } from "../lib/util.js";
3
+ function* indicesFor(slugs, ordered) {
4
+ for (const i of interval(-10, 9)) {
5
+ const indexText = i >= 0 ? `${ordinal(i + 1)} letters` : `${ordinal(i)} letters`;
6
+ const indexed = slugs.map((slug) => slug.at(i) ?? null);
7
+ if (indexed.every((c) => c !== null)) {
8
+ yield { indexText, indexed };
9
+ }
10
+ }
11
+ if (ordered) {
12
+ const indexed = slugs.map((slug, i) => slug.at(i) ?? null);
13
+ if (indexed.every((c) => c !== null)) {
14
+ yield { indexText: "diagonal", indexed };
15
+ }
16
+ }
17
+ if (ordered && slugs.every((slug) => slug.length >= slugs.length)) {
18
+ yield {
19
+ indexText: "antidiagonal",
20
+ indexed: slugs.map((slug, i) => slug.at(slugs.length - i - 1)),
21
+ };
22
+ }
23
+ }
24
+ function allEqual({ indexText, indexed, wordlist }) {
25
+ if (new Set(indexed).size !== 1) {
26
+ return null;
27
+ }
28
+ return {
29
+ name: `${indexText} are equal`,
30
+ logProb: wordlist.letters.probEqual(indexed.length),
31
+ description: [`${indexText} are ${indexed[0]}`],
32
+ };
33
+ }
34
+ function almostEqual({ indexText, indexed, slugs, wordlist, }) {
35
+ const indexedSet = new Set(indexed);
36
+ if (indexedSet.size !== 2) {
37
+ return null;
38
+ }
39
+ let [a, b] = indexedSet;
40
+ let aSlugIndices = indexed.flatMap((w, i) => (w === a ? [i] : []));
41
+ let bSlugIndices = indexed.flatMap((w, i) => (w === b ? [i] : []));
42
+ if (aSlugIndices.length > bSlugIndices.length) {
43
+ [aSlugIndices, bSlugIndices] = [bSlugIndices, aSlugIndices];
44
+ [a, b] = [b, a];
45
+ }
46
+ if (aSlugIndices.length !== 1) {
47
+ return null;
48
+ }
49
+ const [aSlugIndex] = aSlugIndices;
50
+ return {
51
+ name: `${indexText} are almost equal`,
52
+ logProb: wordlist.letters.probAlmostEqual(indexed.length),
53
+ description: [
54
+ `'${slugs[aSlugIndex]}' ${indexText} is '${a}'`,
55
+ `others ${indexText} are '${b}'`,
56
+ ],
57
+ };
58
+ }
59
+ function onlyTwo({ indexText, indexed, slugs, wordlist, }) {
60
+ const indexedSet = new Set(indexed);
61
+ if (indexedSet.size !== 2) {
62
+ return null;
63
+ }
64
+ const [a, b] = indexedSet;
65
+ const aSlugIndices = indexed.flatMap((w, i) => (w === a ? [i] : []));
66
+ const bSlugIndices = indexed.flatMap((w, i) => (w === b ? [i] : []));
67
+ return {
68
+ name: `${indexText} have only two values`,
69
+ logProb: wordlist.letters.probTwoDistinct(indexed.length),
70
+ description: [
71
+ `${aSlugIndices.map((i) => `'${slugs[i]}'`).join(", ")} ${indexText} are '${a}'`,
72
+ `${bSlugIndices.map((i) => `'${slugs[i]}'`).join(", ")} ${indexText} are '${b}'`,
73
+ ],
74
+ };
75
+ }
76
+ function word({ indexText, indexed, wordlist }) {
77
+ // TODO: isPhrase?
78
+ if (!wordlist.isWord(indexed.join(""))) {
79
+ return null;
80
+ }
81
+ return {
82
+ name: `${indexText} are a word`,
83
+ logProb: wordlist.letters.probWord(indexed.length),
84
+ description: [`${indexText} are '${indexed.join("")}'`],
85
+ };
86
+ }
87
+ function anagram({ indexText, indexed, wordlist }) {
88
+ const anagrams = wordlist.anagrams(indexed.join(""));
89
+ if (anagrams.length === 0) {
90
+ return null;
91
+ }
92
+ return {
93
+ name: `${indexText} anagram to a word`,
94
+ logProb: wordlist.letters.probAnagram(indexed.length),
95
+ description: [`${indexText} anagram to ${anagrams.join(", ")}`],
96
+ };
97
+ }
98
+ function consecutive({ indexText, indexed, wordlist, }) {
99
+ const sorted = indexed
100
+ .slice()
101
+ .map((w) => w.charCodeAt(0))
102
+ .sort((a, b) => a - b);
103
+ if (getArithmeticSequenceInfo(sorted)?.step !== 1) {
104
+ return null;
105
+ }
106
+ return {
107
+ name: `${indexText} are consecutive`,
108
+ logProb: wordlist.letters.probConsecutive(indexed.length),
109
+ description: [`${indexText} are ${indexed.join(", ")}`],
110
+ };
111
+ }
112
+ function paired({ indexText, indexed, slugs, wordlist, }) {
113
+ const byIndexed = LetterIndices.from(indexed.join(""));
114
+ const countSet = byIndexed.countSet();
115
+ if (countSet.size !== 1 || Array.from(countSet)[0] !== 2) {
116
+ return null;
117
+ }
118
+ return {
119
+ name: `${indexText} can be paired`,
120
+ logProb: wordlist.letters.probPaired(indexed.length),
121
+ description: Array.from(byIndexed.entries(), ([letter, slugIndices]) => {
122
+ return `${slugIndices.map((i) => `'${slugs[i]}'`).join(", ")} ${indexText} are '${letter}'`;
123
+ }),
124
+ };
125
+ }
126
+ /** Links of the form "the nth indices are..." */
127
+ export function indexingLinker(wordlist) {
128
+ return {
129
+ name: "indexing linker",
130
+ eval: (slugs, { ordered }) => {
131
+ const indices = Array.from(indicesFor(slugs, ordered));
132
+ return indices.flatMap(({ indexText, indexed }) => {
133
+ const props = {
134
+ indexText,
135
+ indexed,
136
+ slugs,
137
+ wordlist,
138
+ };
139
+ return [
140
+ allEqual(props),
141
+ almostEqual(props),
142
+ onlyTwo(props),
143
+ ordered ? word(props) : null,
144
+ anagram(props),
145
+ consecutive(props),
146
+ paired(props),
147
+ ].filter((l) => l !== null);
148
+ });
149
+ },
150
+ };
151
+ }
152
+ //# sourceMappingURL=indexing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexing.js","sourceRoot":"","sources":["../../src/linkers/indexing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { LengthDistribution } from "../lib/lengthDistribution.js";
2
+ import type { Linker } from "./index.js";
3
+ /** Length-based linker. */
4
+ export declare function lengthLinker(distribution: LengthDistribution): Linker;
5
+ //# sourceMappingURL=length.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"length.d.ts","sourceRoot":"","sources":["../../src/linkers/length.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,YAAY,CAAC;AAqGtD,2BAA2B;AAC3B,wBAAgB,YAAY,CAAC,YAAY,EAAE,kBAAkB,GAAG,MAAM,CAiBrE"}
@@ -0,0 +1,101 @@
1
+ import { getArithmeticSequenceInfo } from "../lib/util.js";
2
+ function allEqual({ distribution, lengthSet }) {
3
+ if (lengthSet.size !== 1) {
4
+ return null;
5
+ }
6
+ const [length] = Array.from(lengthSet);
7
+ return {
8
+ name: "all lengths equal",
9
+ logProb: distribution.probEqual(lengthSet.size),
10
+ description: [`all lengths are ${length.toString()}`],
11
+ };
12
+ }
13
+ function onlyTwo({ distribution, lengthSet, slugs, }) {
14
+ if (lengthSet.size !== 2) {
15
+ return null;
16
+ }
17
+ const [a, b] = Array.from(lengthSet);
18
+ const aLength = slugs.filter((w) => w.length === a);
19
+ const bLength = slugs.filter((w) => w.length === b);
20
+ const aLogProb = distribution.probEqual(aLength.length);
21
+ const bLogProb = distribution.probEqual(bLength.length);
22
+ return {
23
+ name: "only two lengths",
24
+ logProb: aLogProb.mul(bLogProb),
25
+ description: [
26
+ `length ${a.toString()}: ${aLength.join(", ")}`,
27
+ `length ${b.toString()}: ${bLength.join(", ")}`,
28
+ ],
29
+ };
30
+ }
31
+ function equalMod2({ distribution, lengths }) {
32
+ if (new Set(lengths.map((l) => l % 2)).size !== 1) {
33
+ return null;
34
+ }
35
+ const parity = lengths[0] % 2;
36
+ return {
37
+ name: `all lengths are ${parity === 0 ? "even" : "odd"}`,
38
+ logProb: distribution.probEqualMod2(lengths.length),
39
+ description: [`all lengths are ${parity === 0 ? "even" : "odd"}`],
40
+ };
41
+ }
42
+ function equalMod3({ distribution, lengths }) {
43
+ if (new Set(lengths.map((l) => l % 3)).size !== 1) {
44
+ return null;
45
+ }
46
+ return {
47
+ name: "all lengths are equal mod 3",
48
+ logProb: distribution.probEqualMod3(lengths.length),
49
+ description: [`all lengths are equal mod 3`],
50
+ };
51
+ }
52
+ function consecutive({ distribution, lengths }) {
53
+ if (getArithmeticSequenceInfo(lengths)?.step !== 1) {
54
+ return null;
55
+ }
56
+ return {
57
+ name: "lengths are consecutive",
58
+ logProb: distribution.probConsecutive(lengths.length),
59
+ description: [`lengths are ${lengths.join(", ")}`],
60
+ };
61
+ }
62
+ function paired({ distribution, slugs }) {
63
+ const byLength = new Map();
64
+ for (const slug of slugs) {
65
+ if (!byLength.has(slug.length)) {
66
+ byLength.set(slug.length, []);
67
+ }
68
+ byLength.get(slug.length).push(slug);
69
+ }
70
+ const lengthCounter = new Set(Array.from(byLength.values(), (slugs) => slugs.length));
71
+ if (lengthCounter.size === 1 && Array.from(lengthCounter)[0] === 2) {
72
+ return {
73
+ name: "lengths can be paired",
74
+ logProb: distribution.probPaired(slugs.length),
75
+ description: Array.from(byLength.entries(), ([, slugs]) => {
76
+ return slugs.join(" and ");
77
+ }),
78
+ };
79
+ }
80
+ return null;
81
+ }
82
+ /** Length-based linker. */
83
+ export function lengthLinker(distribution) {
84
+ return {
85
+ name: "slug lengths",
86
+ eval: (slugs) => {
87
+ const lengths = slugs.map((w) => w.length).sort();
88
+ const lengthSet = new Set(lengths);
89
+ const props = { distribution, lengthSet, lengths, slugs };
90
+ return [
91
+ allEqual(props),
92
+ onlyTwo(props),
93
+ equalMod2(props),
94
+ equalMod3(props),
95
+ consecutive(props),
96
+ paired(props),
97
+ ].filter((l) => l !== null);
98
+ },
99
+ };
100
+ }
101
+ //# sourceMappingURL=length.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"length.js","sourceRoot":"","sources":["../../src/linkers/length.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { LetterDistribution } from "../lib/letterDistribution.js";
2
+ import type { Linker } from "./index.js";
3
+ export declare function letterDistributionLinker(distribution: LetterDistribution): Linker;
4
+ //# sourceMappingURL=letterDistribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letterDistribution.d.ts","sourceRoot":"","sources":["../../src/linkers/letterDistribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAU,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,YAAY,CAAC;AA8CtD,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,kBAAkB,GAC/B,MAAM,CAaR"}
@@ -0,0 +1,46 @@
1
+ import { LetterDistribution, VOWELS } from "../lib/letterDistribution.js";
2
+ function unusual({ distribution, slugs }) {
3
+ const all = slugs.join("");
4
+ const { high, low } = distribution.outliers(all);
5
+ if (high.length > 0 || low.length > 0) {
6
+ return {
7
+ name: "unusual letter distribution",
8
+ logProb: distribution.prob(all),
9
+ description: [
10
+ ...(high ? [`over-represented: ${high}`] : []),
11
+ ...(low ? [`under-represented: ${low}`] : []),
12
+ ],
13
+ };
14
+ }
15
+ return null;
16
+ }
17
+ function equalVowelPattern({ distribution, slugs }) {
18
+ const minLength = Math.min(...slugs.map((s) => s.length));
19
+ const shortest = slugs.find((s) => s.length === minLength);
20
+ const pattern = Array.from(shortest, (letter) => VOWELS.includes(letter) ? "V" : "C").join("");
21
+ for (const other of slugs) {
22
+ for (let i = 0; i < minLength; i++) {
23
+ if (VOWELS.includes(other[i]) !== (pattern[i] === "V")) {
24
+ return null;
25
+ }
26
+ }
27
+ }
28
+ return {
29
+ name: "start with the same vowel-consonant pattern",
30
+ logProb: distribution.probEqualVowelPattern(slugs.length, minLength),
31
+ description: [`all start with ${pattern}`],
32
+ };
33
+ }
34
+ export function letterDistributionLinker(distribution) {
35
+ return {
36
+ name: "letter distribution",
37
+ eval: (slugs) => {
38
+ const props = {
39
+ distribution,
40
+ slugs,
41
+ };
42
+ return [unusual(props), equalVowelPattern(props)].filter((l) => l !== null);
43
+ },
44
+ };
45
+ }
46
+ //# sourceMappingURL=letterDistribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"letterDistribution.js","sourceRoot":"","sources":["../../src/linkers/letterDistribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAW1E,SAAS,OAAO,CAAC,EAAE,YAAY,EAAE,KAAK,EAAS;IAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO;YACL,IAAI,EAAE,6BAA6B;YACnC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;YAC/B,WAAW,EAAE;gBACX,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9C;SACF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,EAAE,YAAY,EAAE,KAAK,EAAS;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAE,CAAC;IAC5D,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE,CAC9C,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CACpC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;gBACxD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,6CAA6C;QACnD,OAAO,EAAE,YAAY,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;QACpE,WAAW,EAAE,CAAC,kBAAkB,OAAO,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,YAAgC;IAEhC,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YACd,MAAM,KAAK,GAAG;gBACZ,YAAY;gBACZ,KAAK;aACN,CAAC;YACF,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CACtD,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,KAAK,IAAI,CACpC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Wordlist } from "../lib/wordlist.js";
2
+ import type { Linker } from "./index.js";
3
+ /** Other links. */
4
+ export declare function otherLinker(wordlist: Wordlist): Linker;
5
+ //# sourceMappingURL=other.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"other.d.ts","sourceRoot":"","sources":["../../src/linkers/other.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,YAAY,CAAC;AAkGtD,mBAAmB;AACnB,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAatD"}
@@ -0,0 +1,90 @@
1
+ import { VOWELS } from "../lib/letterDistribution.js";
2
+ import { LogNum } from "../lib/logNum.js";
3
+ import { enumerate } from "../lib/util.js";
4
+ function unusualLetters({ slugs, wordlist }) {
5
+ const all = Array.from(slugs.join(""));
6
+ const { high, low } = wordlist.letters.outliers(all);
7
+ if (high.length > 0 || low.length > 0) {
8
+ return {
9
+ name: "unusual letter distribution",
10
+ logProb: wordlist.letters.probUnordered(all),
11
+ description: [
12
+ ...(high.length > 0 ? [`over-represented: ${high.join(", ")}`] : []),
13
+ ...(low.length > 0 ? [`under-represented: ${low.join(", ")}`] : []),
14
+ ],
15
+ };
16
+ }
17
+ return null;
18
+ }
19
+ function equalVowelPattern(start, { slugs, wordlist }) {
20
+ const minLength = Math.min(...slugs.map((s) => s.length));
21
+ const shortest = slugs.find((s) => s.length === minLength);
22
+ const pattern = Array.from(shortest, (letter) => VOWELS.includes(letter) ? "V" : "C").join("");
23
+ const matchesVowelPattern = (other) => {
24
+ const offset = start ? 0 : other.length - minLength;
25
+ for (const [i, vc] of enumerate(pattern)) {
26
+ if (VOWELS.includes(other[offset + i]) !== (vc === "V")) {
27
+ return false;
28
+ }
29
+ }
30
+ return true;
31
+ };
32
+ if (!slugs.every(matchesVowelPattern)) {
33
+ return null;
34
+ }
35
+ return {
36
+ name: `${start ? "start" : "end"} with the same vowel-consonant pattern`,
37
+ logProb: wordlist[start ? "prefixes" : "suffixes"].probEqualVowelPattern(slugs.length, minLength),
38
+ description: [`all ${start ? "start" : "end"} with ${pattern}`],
39
+ };
40
+ }
41
+ function sharedAffixes({ slugs, wordlist }) {
42
+ const shared = new Map();
43
+ for (const suffixOf of slugs) {
44
+ for (const prefixOf of slugs) {
45
+ if (prefixOf === suffixOf) {
46
+ continue;
47
+ }
48
+ let length = Math.min(prefixOf.length, suffixOf.length);
49
+ for (; length > 1; length--) {
50
+ if (prefixOf.slice(0, length) !== suffixOf.slice(-length)) {
51
+ continue;
52
+ }
53
+ const currentBest = shared.get(suffixOf)?.length ?? 0;
54
+ if (length > currentBest) {
55
+ shared.set(suffixOf, { prefixOf, length });
56
+ }
57
+ }
58
+ }
59
+ }
60
+ if (shared.size <= 1) {
61
+ return null;
62
+ }
63
+ return {
64
+ name: "multiple shared suffixes and prefixes",
65
+ // This is an underestimate because it assumes independence.
66
+ logProb: LogNum.prod(Array.from(shared.values(), ({ length }) => {
67
+ return wordlist.probSharedAffix(length);
68
+ })),
69
+ description: Array.from(shared.entries(), ([suffixOf, { prefixOf, length }]) => `${suffixOf.slice(0, -length)}${suffixOf.slice(-length).toUpperCase()} ${prefixOf
70
+ .slice(0, length)
71
+ .toUpperCase()}${prefixOf.slice(length)}`),
72
+ };
73
+ }
74
+ // TODO at each index, there's exactly one repeated letter
75
+ /** Other links. */
76
+ export function otherLinker(wordlist) {
77
+ return {
78
+ name: "other links",
79
+ eval: (slugs) => {
80
+ const props = { slugs, wordlist };
81
+ return [
82
+ unusualLetters(props),
83
+ equalVowelPattern(true, props),
84
+ equalVowelPattern(false, props),
85
+ sharedAffixes(props),
86
+ ].filter((l) => l !== null);
87
+ },
88
+ };
89
+ }
90
+ //# sourceMappingURL=other.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"other.js","sourceRoot":"","sources":["../../src/linkers/other.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Parse an input to a list of slugs.
3
+ *
4
+ * If the input has newlines, we split by newlines. Otherwise, if commas
5
+ * exist, we split by commas. Otherwise, we split by spaces.
6
+ */
7
+ export declare function parse(words: string | readonly string[]): string[];
8
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAajE"}
package/dist/parse.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Parse an input to a list of slugs.
3
+ *
4
+ * If the input has newlines, we split by newlines. Otherwise, if commas
5
+ * exist, we split by commas. Otherwise, we split by spaces.
6
+ */
7
+ export function parse(words) {
8
+ if (typeof words === "string") {
9
+ if (words.includes("\n")) {
10
+ words = words.split("\n");
11
+ }
12
+ else if (words.includes(",")) {
13
+ words = words.split(",");
14
+ }
15
+ else {
16
+ words = words.split(" ");
17
+ }
18
+ }
19
+ return words
20
+ .map((w) => w.toLowerCase().replace(/[^a-z]/g, ""))
21
+ .filter((w) => w.length > 0);
22
+ }
23
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,KAAiC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;SAClD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,84 @@
1
+ import type { Linker } from "./linkers/index.js";
2
+ /**
3
+ * A Link is a relationship between a (possibly ordered) set of words, with how
4
+ * strong it is quantified via its score.
5
+ */
6
+ export type Link = {
7
+ /** The name of the link. */
8
+ name: string;
9
+ /**
10
+ * Any additional information about the link. Typically, this would be an
11
+ * explanation for why the words satisfy the given link.
12
+ */
13
+ description: readonly string[];
14
+ /**
15
+ * The score of the link. A higher score means it's more likely to be
16
+ * important (because it's less likely to happen by chance).
17
+ *
18
+ * This is calculated as the negative of the log probability we'd expect to
19
+ * see this link, if each word was replaced with a random puzzle answer,
20
+ * rounded to 1 decimal place.
21
+ */
22
+ score: number;
23
+ };
24
+ /** Options for Puzlink.link(). */
25
+ export type LinkOptions = {
26
+ /**
27
+ * Whether to return links via a generator instead of a list. If true, links
28
+ * will be returned *unsorted*, and the limit option will be ignored.
29
+ *
30
+ * Defaults to false.
31
+ */
32
+ lazy?: boolean;
33
+ /**
34
+ * Limit the number of links returned. Pass null or Infinity to return
35
+ * all links.
36
+ *
37
+ * Defaults to 10.
38
+ */
39
+ limit?: number | null;
40
+ /**
41
+ * Only report features that are satisfied by either 0, or at least
42
+ * minFeatureRatio of the words.
43
+ *
44
+ * Defaults to 0.5.
45
+ */
46
+ minFeatureRatio?: number;
47
+ /**
48
+ * Set to true if the input has a particular order. Some of the links we use
49
+ * apply only if the words have a given order.
50
+ *
51
+ * Defaults to true if the words are NOT alphabetically sorted.
52
+ */
53
+ ordered?: boolean;
54
+ };
55
+ export declare class Puzlink {
56
+ linkers: Linker[];
57
+ constructor(wordlist: Record<string, number>);
58
+ /** Create a Puzlink instance by downloading the cromulence wordlist. */
59
+ static download(): Promise<Puzlink>;
60
+ /**
61
+ * Parse an input to a list of slugs.
62
+ *
63
+ * If the input has newlines, we split by newlines. Otherwise, if commas
64
+ * exist, we split by commas. Otherwise, we split by spaces.
65
+ */
66
+ static parse(words: string | readonly string[]): string[];
67
+ private linkLazy;
68
+ /**
69
+ * Given a list of words, returns a list of links they share, sorted from
70
+ * highest to lowest score.
71
+ */
72
+ link(
73
+ /** The words to link. See Puzlink.parse for how these are parsed. */
74
+ words: string | readonly string[], options?: LinkOptions & {
75
+ lazy?: false;
76
+ }): Link[];
77
+ /** Given a list of words, returns a generator of links they share. */
78
+ link(
79
+ /** The words to link. See Puzlink.parse for how these are parsed. */
80
+ words: string | readonly string[], options?: LinkOptions & {
81
+ lazy: true;
82
+ }): Generator<Link>;
83
+ }
84
+ //# sourceMappingURL=puzlink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"puzlink.d.ts","sourceRoot":"","sources":["../src/puzlink.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAIjD;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,kCAAkC;AAClC,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qBAAa,OAAO;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;gBAEN,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI5C,wEAAwE;WAC3D,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE;IAIzD,OAAO,CAAE,QAAQ;IAejB;;;OAGG;IACH,IAAI;IACF,qEAAqE;IACrE,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EACjC,OAAO,CAAC,EAAE,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,KAAK,CAAA;KAAE,GACvC,IAAI,EAAE;IACT,sEAAsE;IACtE,IAAI;IACF,qEAAqE;IACrE,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EACjC,OAAO,CAAC,EAAE,WAAW,GAAG;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GACrC,SAAS,CAAC,IAAI,CAAC;CAuCnB"}
@@ -0,0 +1,59 @@
1
+ import { loadWordlist } from "cromulence";
2
+ import { Wordlist } from "./lib/wordlist.js";
3
+ import { allLinkers } from "./linkers/index.js";
4
+ import { parse } from "./parse.js";
5
+ export class Puzlink {
6
+ linkers;
7
+ constructor(wordlist) {
8
+ this.linkers = allLinkers(new Wordlist(wordlist));
9
+ }
10
+ /** Create a Puzlink instance by downloading the cromulence wordlist. */
11
+ static async download() {
12
+ return new Puzlink(await loadWordlist());
13
+ }
14
+ /**
15
+ * Parse an input to a list of slugs.
16
+ *
17
+ * If the input has newlines, we split by newlines. Otherwise, if commas
18
+ * exist, we split by commas. Otherwise, we split by spaces.
19
+ */
20
+ static parse(words) {
21
+ return parse(words);
22
+ }
23
+ *linkLazy(slugs, options) {
24
+ for (const linker of this.linkers) {
25
+ for (const partialLink of linker.eval(slugs, options)) {
26
+ yield {
27
+ name: linker.name,
28
+ score: Math.round(partialLink.logProb.toLog() * -10) / 10,
29
+ ...partialLink,
30
+ };
31
+ }
32
+ }
33
+ }
34
+ link(
35
+ /** The words to link. See Puzlink.parse for how these are parsed. */
36
+ words, { lazy = false, limit = 10, minFeatureRatio = 0.5, ordered, } = {}) {
37
+ const slugs = Puzlink.parse(words);
38
+ if (slugs.length === 0) {
39
+ return lazy
40
+ ? (function* () {
41
+ // empty
42
+ })()
43
+ : [];
44
+ }
45
+ if (ordered === undefined) {
46
+ const sortedSlugs = slugs.slice().sort();
47
+ const isSorted = slugs.every((slug, i) => slug === sortedSlugs[i]);
48
+ ordered = !isSorted;
49
+ }
50
+ const options = { lazy, limit, ordered, minFeatureRatio };
51
+ if (lazy) {
52
+ return this.linkLazy(slugs, options);
53
+ }
54
+ return Array.from(this.linkLazy(slugs, options))
55
+ .sort((a, b) => (a.score > b.score ? -1 : 1))
56
+ .slice(0, limit ?? Infinity);
57
+ }
58
+ }
59
+ //# sourceMappingURL=puzlink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"puzlink.js","sourceRoot":"","sources":["../src/puzlink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAyDnC,MAAM,OAAO,OAAO;IAClB,OAAO,CAAW;IAElB,YAAY,QAAgC;QAC1C,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,wEAAwE;IACxE,MAAM,CAAC,KAAK,CAAC,QAAQ;QACnB,OAAO,IAAI,OAAO,CAAC,MAAM,YAAY,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,KAAiC;QAC5C,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IAEO,CAAC,QAAQ,CACf,KAAe,EACf,OAA8B;QAE9B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;gBACtD,MAAM;oBACJ,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE;oBACzD,GAAG,WAAW;iBACf,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAiBD,IAAI;IACF,qEAAqE;IACrE,KAAiC,EACjC,EACE,IAAI,GAAG,KAAK,EACZ,KAAK,GAAG,EAAE,EACV,eAAe,GAAG,GAAG,EACrB,OAAO,MACQ,EAAE;QAEnB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAEnC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI;gBACT,CAAC,CAAC,CAAC,QAAQ,CAAC;oBACR,QAAQ;gBACV,CAAC,CAAC,EAAE;gBACN,CAAC,CAAC,EAAE,CAAC;QACT,CAAC;QAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YACnE,OAAO,GAAG,CAAC,QAAQ,CAAC;QACtB,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;QAE1D,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;aAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5C,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI,QAAQ,CAAC,CAAC;IACjC,CAAC;CAGF"}