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.
- package/LICENSE.md +21 -0
- package/README.md +35 -0
- package/dist/data/answerLengths.d.ts +10 -0
- package/dist/data/answerLengths.d.ts.map +1 -0
- package/dist/data/answerLengths.js +63 -0
- package/dist/data/answerLengths.js.map +1 -0
- package/dist/data/categories/compass.d.ts +3 -0
- package/dist/data/categories/compass.d.ts.map +1 -0
- package/dist/data/categories/compass.js +11 -0
- package/dist/data/categories/compass.js.map +1 -0
- package/dist/data/categories/countryAlpha2.d.ts +3 -0
- package/dist/data/categories/countryAlpha2.d.ts.map +1 -0
- package/dist/data/categories/countryAlpha2.js +252 -0
- package/dist/data/categories/countryAlpha2.js.map +1 -0
- package/dist/data/categories/countryAlpha3.d.ts +3 -0
- package/dist/data/categories/countryAlpha3.d.ts.map +1 -0
- package/dist/data/categories/countryAlpha3.js +252 -0
- package/dist/data/categories/countryAlpha3.js.map +1 -0
- package/dist/data/categories/daysOfTheWeek.d.ts +3 -0
- package/dist/data/categories/daysOfTheWeek.d.ts.map +1 -0
- package/dist/data/categories/daysOfTheWeek.js +10 -0
- package/dist/data/categories/daysOfTheWeek.js.map +1 -0
- package/dist/data/categories/elementSymbols.d.ts +3 -0
- package/dist/data/categories/elementSymbols.d.ts.map +1 -0
- package/dist/data/categories/elementSymbols.js +121 -0
- package/dist/data/categories/elementSymbols.js.map +1 -0
- package/dist/data/categories/greekLetters.d.ts +3 -0
- package/dist/data/categories/greekLetters.d.ts.map +1 -0
- package/dist/data/categories/greekLetters.js +27 -0
- package/dist/data/categories/greekLetters.js.map +1 -0
- package/dist/data/categories/months.d.ts +3 -0
- package/dist/data/categories/months.d.ts.map +1 -0
- package/dist/data/categories/months.js +15 -0
- package/dist/data/categories/months.js.map +1 -0
- package/dist/data/categories/natoAlphabet.d.ts +3 -0
- package/dist/data/categories/natoAlphabet.d.ts.map +1 -0
- package/dist/data/categories/natoAlphabet.js +29 -0
- package/dist/data/categories/natoAlphabet.js.map +1 -0
- package/dist/data/categories/numbers.d.ts +3 -0
- package/dist/data/categories/numbers.d.ts.map +1 -0
- package/dist/data/categories/numbers.js +16 -0
- package/dist/data/categories/numbers.js.map +1 -0
- package/dist/data/categories/romanNumerals.d.ts +3 -0
- package/dist/data/categories/romanNumerals.d.ts.map +1 -0
- package/dist/data/categories/romanNumerals.js +134 -0
- package/dist/data/categories/romanNumerals.js.map +1 -0
- package/dist/data/categories/solfege.d.ts +3 -0
- package/dist/data/categories/solfege.d.ts.map +1 -0
- package/dist/data/categories/solfege.js +11 -0
- package/dist/data/categories/solfege.js.map +1 -0
- package/dist/data/categories/usStateAbbreviations.d.ts +3 -0
- package/dist/data/categories/usStateAbbreviations.d.ts.map +1 -0
- package/dist/data/categories/usStateAbbreviations.js +53 -0
- package/dist/data/categories/usStateAbbreviations.js.map +1 -0
- package/dist/data/categories.d.ts +10 -0
- package/dist/data/categories.d.ts.map +1 -0
- package/dist/data/categories.js +31 -0
- package/dist/data/categories.js.map +1 -0
- package/dist/data/knownLogProbs.d.ts +6 -0
- package/dist/data/knownLogProbs.d.ts.map +1 -0
- package/dist/data/knownLogProbs.js +2975 -0
- package/dist/data/knownLogProbs.js.map +1 -0
- package/dist/data/morse.d.ts +2 -0
- package/dist/data/morse.d.ts.map +1 -0
- package/dist/data/morse.js +29 -0
- package/dist/data/morse.js.map +1 -0
- package/dist/data/scrabble.d.ts +2 -0
- package/dist/data/scrabble.d.ts.map +1 -0
- package/dist/data/scrabble.js +29 -0
- package/dist/data/scrabble.js.map +1 -0
- package/dist/features/index.d.ts +32 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +79 -0
- package/dist/features/index.js.map +1 -0
- package/dist/features/letterCount.d.ts +7 -0
- package/dist/features/letterCount.d.ts.map +1 -0
- package/dist/features/letterCount.js +121 -0
- package/dist/features/letterCount.js.map +1 -0
- package/dist/features/letterSequence.d.ts +7 -0
- package/dist/features/letterSequence.d.ts.map +1 -0
- package/dist/features/letterSequence.js +155 -0
- package/dist/features/letterSequence.js.map +1 -0
- package/dist/features/logProbCache.d.ts +16 -0
- package/dist/features/logProbCache.d.ts.map +1 -0
- package/dist/features/logProbCache.js +36 -0
- package/dist/features/logProbCache.js.map +1 -0
- package/dist/features/other.d.ts +4 -0
- package/dist/features/other.d.ts.map +1 -0
- package/dist/features/other.js +190 -0
- package/dist/features/other.js.map +1 -0
- package/dist/features/substring.d.ts +3 -0
- package/dist/features/substring.d.ts.map +1 -0
- package/dist/features/substring.js +146 -0
- package/dist/features/substring.js.map +1 -0
- package/dist/features/wordplay.d.ts +7 -0
- package/dist/features/wordplay.d.ts.map +1 -0
- package/dist/features/wordplay.js +387 -0
- package/dist/features/wordplay.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/affixDistribution.d.ts +26 -0
- package/dist/lib/affixDistribution.d.ts.map +1 -0
- package/dist/lib/affixDistribution.js +105 -0
- package/dist/lib/affixDistribution.js.map +1 -0
- package/dist/lib/counter.d.ts +23 -0
- package/dist/lib/counter.d.ts.map +1 -0
- package/dist/lib/counter.js +55 -0
- package/dist/lib/counter.js.map +1 -0
- package/dist/lib/distribution.d.ts +40 -0
- package/dist/lib/distribution.d.ts.map +1 -0
- package/dist/lib/distribution.js +176 -0
- package/dist/lib/distribution.js.map +1 -0
- package/dist/lib/lengthDistribution.d.ts +30 -0
- package/dist/lib/lengthDistribution.d.ts.map +1 -0
- package/dist/lib/lengthDistribution.js +137 -0
- package/dist/lib/lengthDistribution.js.map +1 -0
- package/dist/lib/letterBitset.d.ts +49 -0
- package/dist/lib/letterBitset.d.ts.map +1 -0
- package/dist/lib/letterBitset.js +101 -0
- package/dist/lib/letterBitset.js.map +1 -0
- package/dist/lib/letterDistribution.d.ts +60 -0
- package/dist/lib/letterDistribution.d.ts.map +1 -0
- package/dist/lib/letterDistribution.js +230 -0
- package/dist/lib/letterDistribution.js.map +1 -0
- package/dist/lib/letterIndices.d.ts +13 -0
- package/dist/lib/letterIndices.d.ts.map +1 -0
- package/dist/lib/letterIndices.js +41 -0
- package/dist/lib/letterIndices.js.map +1 -0
- package/dist/lib/logCounter.d.ts +23 -0
- package/dist/lib/logCounter.d.ts.map +1 -0
- package/dist/lib/logCounter.js +49 -0
- package/dist/lib/logCounter.js.map +1 -0
- package/dist/lib/logNum.d.ts +36 -0
- package/dist/lib/logNum.d.ts.map +1 -0
- package/dist/lib/logNum.js +193 -0
- package/dist/lib/logNum.js.map +1 -0
- package/dist/lib/memoize.d.ts +5 -0
- package/dist/lib/memoize.d.ts.map +1 -0
- package/dist/lib/memoize.js +104 -0
- package/dist/lib/memoize.js.map +1 -0
- package/dist/lib/util.d.ts +30 -0
- package/dist/lib/util.d.ts.map +1 -0
- package/dist/lib/util.js +111 -0
- package/dist/lib/util.js.map +1 -0
- package/dist/lib/wordlist.d.ts +66 -0
- package/dist/lib/wordlist.d.ts.map +1 -0
- package/dist/lib/wordlist.js +166 -0
- package/dist/lib/wordlist.js.map +1 -0
- package/dist/linkers/index.d.ts +34 -0
- package/dist/linkers/index.d.ts.map +1 -0
- package/dist/linkers/index.js +25 -0
- package/dist/linkers/index.js.map +1 -0
- package/dist/linkers/indexing.d.ts +5 -0
- package/dist/linkers/indexing.d.ts.map +1 -0
- package/dist/linkers/indexing.js +152 -0
- package/dist/linkers/indexing.js.map +1 -0
- package/dist/linkers/length.d.ts +5 -0
- package/dist/linkers/length.d.ts.map +1 -0
- package/dist/linkers/length.js +101 -0
- package/dist/linkers/length.js.map +1 -0
- package/dist/linkers/letterDistribution.d.ts +4 -0
- package/dist/linkers/letterDistribution.d.ts.map +1 -0
- package/dist/linkers/letterDistribution.js +46 -0
- package/dist/linkers/letterDistribution.js.map +1 -0
- package/dist/linkers/other.d.ts +5 -0
- package/dist/linkers/other.d.ts.map +1 -0
- package/dist/linkers/other.js +90 -0
- package/dist/linkers/other.js.map +1 -0
- package/dist/parse.d.ts +8 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +23 -0
- package/dist/parse.js.map +1 -0
- package/dist/puzlink.d.ts +84 -0
- package/dist/puzlink.d.ts.map +1 -0
- package/dist/puzlink.js +59 -0
- package/dist/puzlink.js.map +1 -0
- package/package.json +57 -0
- package/src/data/answerLengths.ts +63 -0
- package/src/data/categories/README.md +3 -0
- package/src/data/categories/compass.ts +1 -0
- package/src/data/categories/countryAlpha2.ts +251 -0
- package/src/data/categories/countryAlpha3.ts +251 -0
- package/src/data/categories/daysOfTheWeek.ts +1 -0
- package/src/data/categories/elementSymbols.ts +120 -0
- package/src/data/categories/greekLetters.ts +26 -0
- package/src/data/categories/months.ts +14 -0
- package/src/data/categories/natoAlphabet.ts +28 -0
- package/src/data/categories/numbers.ts +15 -0
- package/src/data/categories/romanNumerals.ts +133 -0
- package/src/data/categories/solfege.ts +1 -0
- package/src/data/categories/txt/compass.txt +8 -0
- package/src/data/categories/txt/daysOfTheWeek.txt +7 -0
- package/src/data/categories/txt/elementSymbols.txt +118 -0
- package/src/data/categories/txt/greekLetters.txt +24 -0
- package/src/data/categories/txt/months.txt +12 -0
- package/src/data/categories/txt/natoAlphabet.txt +26 -0
- package/src/data/categories/txt/numbers.txt +13 -0
- package/src/data/categories/txt/solfege.txt +8 -0
- package/src/data/categories/txt/usStateAbbreviations.txt +50 -0
- package/src/data/categories/usStateAbbreviations.ts +52 -0
- package/src/data/categories.ts +42 -0
- package/src/data/knownLogProbs.ts +2992 -0
- package/src/data/morse.ts +28 -0
- package/src/data/scrabble.ts +28 -0
- package/src/features/index.ts +120 -0
- package/src/features/letterCount.ts +174 -0
- package/src/features/letterSequence.ts +222 -0
- package/src/features/logProbCache.ts +48 -0
- package/src/features/other.ts +214 -0
- package/src/features/substring.ts +173 -0
- package/src/features/wordplay.ts +428 -0
- package/src/index.ts +3 -0
- package/src/lib/affixDistribution.ts +70 -0
- package/src/lib/counter.ts +71 -0
- package/src/lib/distribution.ts +162 -0
- package/src/lib/lengthDistribution.ts +108 -0
- package/src/lib/letterBitset.ts +123 -0
- package/src/lib/letterDistribution.ts +236 -0
- package/src/lib/letterIndices.ts +51 -0
- package/src/lib/logCounter.ts +74 -0
- package/src/lib/logNum.ts +193 -0
- package/src/lib/memoize.ts +136 -0
- package/src/lib/testUtils.ts +1 -0
- package/src/lib/util.ts +150 -0
- package/src/lib/wordlist.ts +162 -0
- package/src/linkers/index.ts +56 -0
- package/src/linkers/indexing.ts +194 -0
- package/src/linkers/length.ts +122 -0
- package/src/linkers/other.ts +117 -0
- package/src/parse.ts +20 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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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"}
|
package/dist/parse.d.ts
ADDED
|
@@ -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"}
|
package/dist/puzlink.js
ADDED
|
@@ -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"}
|