scrabble-solver 2.18.4 → 2.18.5

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 (88) hide show
  1. package/.nx/workspace-data/d/server-process.json +3 -3
  2. package/.nx/workspace-data/file-map.json +488 -488
  3. package/.nx/workspace-data/lockfile-dependencies.hash +1 -1
  4. package/.nx/workspace-data/lockfile-nodes.hash +1 -1
  5. package/.nx/workspace-data/nx_files.nxt +0 -0
  6. package/.nx/workspace-data/parsed-lock-file.dependencies.json +1021 -901
  7. package/.nx/workspace-data/parsed-lock-file.nodes.json +1892 -1478
  8. package/.nx/workspace-data/project-graph.json +3025 -2477
  9. package/CLAUDE.md +1 -1
  10. package/bun.lock +675 -343
  11. package/lerna.json +1 -1
  12. package/package.json +11 -11
  13. package/packages/configs/package.json +3 -3
  14. package/packages/constants/package.json +1 -1
  15. package/packages/dictionaries/package.json +5 -5
  16. package/packages/logger/package.json +1 -1
  17. package/packages/scrabble-solver/.next/BUILD_ID +1 -1
  18. package/packages/scrabble-solver/.next/build-manifest.json +16 -16
  19. package/packages/scrabble-solver/.next/cache/.previewinfo +1 -1
  20. package/packages/scrabble-solver/.next/cache/.rscinfo +1 -1
  21. package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
  22. package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +2 -2
  23. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
  24. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
  25. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
  26. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  27. package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
  28. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
  29. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
  30. package/packages/scrabble-solver/.next/diagnostics/framework.json +1 -1
  31. package/packages/scrabble-solver/.next/next-minimal-server.js.nft.json +1 -1
  32. package/packages/scrabble-solver/.next/next-server.js.nft.json +1 -1
  33. package/packages/scrabble-solver/.next/prerender-manifest.json +4 -4
  34. package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
  35. package/packages/scrabble-solver/.next/server/chunks/30.js +1 -1
  36. package/packages/scrabble-solver/.next/server/chunks/853.js +2 -2
  37. package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
  38. package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
  39. package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
  40. package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
  41. package/packages/scrabble-solver/.next/server/pages/_document.js.nft.json +1 -1
  42. package/packages/scrabble-solver/.next/server/pages/_error.js +1 -1
  43. package/packages/scrabble-solver/.next/server/pages/_error.js.nft.json +1 -1
  44. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  45. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  46. package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
  47. package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -1
  48. package/packages/scrabble-solver/.next/server/pages/api/visit.js.nft.json +1 -1
  49. package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
  50. package/packages/scrabble-solver/.next/server/pages/index.js +1 -1
  51. package/packages/scrabble-solver/.next/server/pages/index.js.nft.json +1 -1
  52. package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
  53. package/packages/scrabble-solver/.next/server/pages/index.meta +1 -0
  54. package/packages/scrabble-solver/.next/server/pages/not-found.html +1 -1
  55. package/packages/scrabble-solver/.next/server/route-cache/PAGES/8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1/$/index.html +29 -0
  56. package/packages/scrabble-solver/.next/server/route-cache/PAGES/8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1/$/index.json +1 -0
  57. package/packages/scrabble-solver/.next/server/route-cache/PAGES/8a5edab282632443219e051e4ade2d1d5bbc671c781051bf1437897cbdfea0f1/$/index.meta +1 -0
  58. package/packages/scrabble-solver/.next/static/{TAqjh9l5VJQOfJ4SzgPk2 → YHx536pklAqlc9UGAXCj8}/_buildManifest.js +1 -1
  59. package/packages/scrabble-solver/.next/static/chunks/101-fee295c7587c0836.js +3 -0
  60. package/packages/scrabble-solver/.next/static/chunks/{256.6a20b23a766cfebd.js → 256.2a4fa7f278e0a97d.js} +1 -1
  61. package/packages/scrabble-solver/.next/static/chunks/827.09f660ca0a951d12.js +1 -0
  62. package/packages/scrabble-solver/.next/static/chunks/framework-988fd6f19d2744e8.js +1 -0
  63. package/packages/scrabble-solver/.next/static/chunks/main-d397eb8af33c5163.js +5 -0
  64. package/packages/scrabble-solver/.next/static/chunks/pages/{_app-9340d51f5a6787fc.js → _app-0c68f165d6de8507.js} +1 -1
  65. package/packages/scrabble-solver/.next/static/chunks/{webpack-d73aa4aae49cd800.js → webpack-31879a8fb6dcffd0.js} +1 -1
  66. package/packages/scrabble-solver/.next/trace +22 -22
  67. package/packages/scrabble-solver/.next/trace-build +1 -1
  68. package/packages/scrabble-solver/package.json +18 -18
  69. package/packages/scrabble-solver/public/service-worker.js +1 -1
  70. package/packages/scrabble-solver/tsconfig.tsbuildinfo +1 -1
  71. package/packages/solver/package.json +6 -6
  72. package/packages/types/package.json +2 -2
  73. package/packages/word-definitions/package.json +3 -3
  74. package/packages/word-lists/package.json +3 -3
  75. package/playwright-report/index.html +6 -6
  76. package/packages/gaddag/build/Gaddag.d.ts +0 -39
  77. package/packages/gaddag/build/Gaddag.js +0 -128
  78. package/packages/gaddag/build/buildGaddag.d.ts +0 -10
  79. package/packages/gaddag/build/buildGaddag.js +0 -360
  80. package/packages/gaddag/build/constants.d.ts +0 -12
  81. package/packages/gaddag/build/constants.js +0 -15
  82. package/packages/gaddag/build/index.d.ts +0 -3
  83. package/packages/gaddag/build/index.js +0 -13
  84. package/packages/scrabble-solver/.next/static/chunks/101-f341f70c10d71212.js +0 -3
  85. package/packages/scrabble-solver/.next/static/chunks/827.c81b92b383a748c9.js +0 -1
  86. package/packages/scrabble-solver/.next/static/chunks/framework-626cbd48ac5aca57.js +0 -1
  87. package/packages/scrabble-solver/.next/static/chunks/main-6e9ac37e28d2b899.js +0 -5
  88. /package/packages/scrabble-solver/.next/static/{TAqjh9l5VJQOfJ4SzgPk2 → YHx536pklAqlc9UGAXCj8}/_ssgManifest.js +0 -0
@@ -1,39 +0,0 @@
1
- /**
2
- * A GADDAG (Gordon, 1994) stored as flat typed arrays for speed and compact serialization.
3
- *
4
- * For every word `w` and every split `1 <= s <= |w|` the automaton accepts
5
- * `reverse(w[0..s)) + ◇ + w[s..)` (the separator is omitted when `s === |w|`).
6
- *
7
- * States are identified by "refs": `ref = (firstArcIndex << 1) | isWordEnd`.
8
- * A `firstArcIndex` of 0 means the state has no outgoing arcs; ref 0 means "no such state".
9
- * Arcs of a state are contiguous; the last one is marked with {@link LAST_ARC_FLAG} in its label.
10
- * An arc label stores the letter index (1..63, 0 = separator) in its low 6 bits.
11
- */
12
- export declare class Gaddag {
13
- /** Arc labels: letter index | LAST_ARC_FLAG. Index 0 is an unused sentinel. */
14
- readonly arcLabels: Uint8Array;
15
- /** Arc targets: encoded state refs. Index 0 is an unused sentinel. */
16
- readonly arcTargets: Int32Array;
17
- /** Ref of the root state. */
18
- readonly rootRef: number;
19
- /** Code point of each letter index (position 0 holds the code point of letter 1). */
20
- readonly charCodes: Int32Array;
21
- private readonly letterByCharCode;
22
- constructor(arcLabels: Uint8Array, arcTargets: Int32Array, rootRef: number, charCodes: Int32Array);
23
- static deserialize(bytes: Uint8Array): Gaddag;
24
- serialize(): Uint8Array;
25
- /** Number of arcs (including the unused sentinel at index 0). */
26
- get arcsCount(): number;
27
- /**
28
- * Follows the arc labeled with `letter` from the state `ref` points at.
29
- * Returns the target ref, or 0 when there is no such arc.
30
- *
31
- * A state's arcs are stored in ascending letter order, so the scan stops as
32
- * soon as it passes the wanted letter.
33
- */
34
- getArc(ref: number, letter: number): number;
35
- /** Maps a code point to its letter index, or -1 when the character is not in the alphabet. */
36
- getLetter(charCode: number): number;
37
- has(word: string): boolean;
38
- hasPrefix(prefix: string): boolean;
39
- }
@@ -1,128 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Gaddag = void 0;
4
- /* eslint-disable no-bitwise */
5
- const constants_1 = require("./constants");
6
- /**
7
- * A GADDAG (Gordon, 1994) stored as flat typed arrays for speed and compact serialization.
8
- *
9
- * For every word `w` and every split `1 <= s <= |w|` the automaton accepts
10
- * `reverse(w[0..s)) + ◇ + w[s..)` (the separator is omitted when `s === |w|`).
11
- *
12
- * States are identified by "refs": `ref = (firstArcIndex << 1) | isWordEnd`.
13
- * A `firstArcIndex` of 0 means the state has no outgoing arcs; ref 0 means "no such state".
14
- * Arcs of a state are contiguous; the last one is marked with {@link LAST_ARC_FLAG} in its label.
15
- * An arc label stores the letter index (1..63, 0 = separator) in its low 6 bits.
16
- */
17
- class Gaddag {
18
- constructor(arcLabels, arcTargets, rootRef, charCodes) {
19
- this.arcLabels = arcLabels;
20
- this.arcTargets = arcTargets;
21
- this.rootRef = rootRef;
22
- this.charCodes = charCodes;
23
- this.letterByCharCode = new Map();
24
- for (let index = 0; index < charCodes.length; ++index) {
25
- this.letterByCharCode.set(charCodes[index], index + 1);
26
- }
27
- }
28
- static deserialize(bytes) {
29
- // Note: an explicit copy (not .slice()) — Buffer.prototype.slice returns a
30
- // view that would keep the misaligned byteOffset.
31
- const aligned = bytes.byteOffset % 4 === 0 ? bytes : new Uint8Array(bytes);
32
- const header = new Int32Array(aligned.buffer, aligned.byteOffset, 4);
33
- if (header[0] !== constants_1.MAGIC) {
34
- throw new Error('Invalid Gaddag data');
35
- }
36
- const letterCount = header[1];
37
- const arcCount = header[2];
38
- const rootRef = header[3];
39
- const charCodes = new Int32Array(aligned.buffer, aligned.byteOffset + 16, letterCount);
40
- const arcTargets = new Int32Array(aligned.buffer, aligned.byteOffset + 16 + 4 * letterCount, arcCount);
41
- const arcLabels = new Uint8Array(aligned.buffer, aligned.byteOffset + 16 + 4 * (letterCount + arcCount), arcCount);
42
- return new Gaddag(arcLabels, arcTargets, rootRef, charCodes);
43
- }
44
- serialize() {
45
- const letterCount = this.charCodes.length;
46
- const arcCount = this.arcTargets.length;
47
- const bytes = new Uint8Array(16 + 4 * (letterCount + arcCount) + arcCount);
48
- const header = new Int32Array(bytes.buffer, 0, 4);
49
- header[0] = constants_1.MAGIC;
50
- header[1] = letterCount;
51
- header[2] = arcCount;
52
- header[3] = this.rootRef;
53
- new Int32Array(bytes.buffer, 16, letterCount).set(this.charCodes);
54
- new Int32Array(bytes.buffer, 16 + 4 * letterCount, arcCount).set(this.arcTargets);
55
- bytes.set(this.arcLabels, 16 + 4 * (letterCount + arcCount));
56
- return bytes;
57
- }
58
- /** Number of arcs (including the unused sentinel at index 0). */
59
- get arcsCount() {
60
- return this.arcTargets.length;
61
- }
62
- /**
63
- * Follows the arc labeled with `letter` from the state `ref` points at.
64
- * Returns the target ref, or 0 when there is no such arc.
65
- *
66
- * A state's arcs are stored in ascending letter order, so the scan stops as
67
- * soon as it passes the wanted letter.
68
- */
69
- getArc(ref, letter) {
70
- let index = ref >>> 1;
71
- if (index === 0) {
72
- return 0;
73
- }
74
- const labels = this.arcLabels;
75
- for (;;) {
76
- const label = labels[index];
77
- const arcLetter = label & constants_1.LETTER_MASK;
78
- if (arcLetter === letter) {
79
- return this.arcTargets[index];
80
- }
81
- if (arcLetter > letter || label >= constants_1.LAST_ARC_FLAG) {
82
- return 0;
83
- }
84
- ++index;
85
- }
86
- }
87
- /** Maps a code point to its letter index, or -1 when the character is not in the alphabet. */
88
- getLetter(charCode) {
89
- return this.letterByCharCode.get(charCode) ?? -1;
90
- }
91
- has(word) {
92
- const length = word.length;
93
- if (length === 0) {
94
- return false;
95
- }
96
- let ref = this.rootRef;
97
- for (let index = length - 1; index >= 0; --index) {
98
- const letter = this.getLetter(word.charCodeAt(index));
99
- if (letter === -1) {
100
- return false;
101
- }
102
- ref = this.getArc(ref, letter);
103
- if (ref === 0) {
104
- return false;
105
- }
106
- }
107
- return (ref & 1) === 1;
108
- }
109
- hasPrefix(prefix) {
110
- const length = prefix.length;
111
- if (length === 0) {
112
- return true;
113
- }
114
- let ref = this.rootRef;
115
- for (let index = length - 1; index >= 0; --index) {
116
- const letter = this.getLetter(prefix.charCodeAt(index));
117
- if (letter === -1) {
118
- return false;
119
- }
120
- ref = this.getArc(ref, letter);
121
- if (ref === 0) {
122
- return false;
123
- }
124
- }
125
- return (ref & 1) === 1 || this.getArc(ref, constants_1.SEPARATOR) !== 0;
126
- }
127
- }
128
- exports.Gaddag = Gaddag;
@@ -1,10 +0,0 @@
1
- import { Gaddag } from './Gaddag';
2
- /**
3
- * Builds a minimal GADDAG from a word list.
4
- *
5
- * The construction generates every GADDAG sequence (`reverse(prefix) [+ ◇ + suffix]`)
6
- * as a compact `(wordIndex << 6) | splitIndex` integer, orders them with an in-place
7
- * MSD radix sort, and feeds them to an incremental minimal-automaton builder
8
- * (Daciuk et al., 2000) backed by typed arrays and an open-addressing state registry.
9
- */
10
- export declare const buildGaddag: (words: string[]) => Gaddag;
@@ -1,360 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildGaddag = void 0;
4
- /* eslint-disable max-depth, max-lines, max-statements, no-bitwise */
5
- const constants_1 = require("./constants");
6
- const Gaddag_1 = require("./Gaddag");
7
- /**
8
- * Builds a minimal GADDAG from a word list.
9
- *
10
- * The construction generates every GADDAG sequence (`reverse(prefix) [+ ◇ + suffix]`)
11
- * as a compact `(wordIndex << 6) | splitIndex` integer, orders them with an in-place
12
- * MSD radix sort, and feeds them to an incremental minimal-automaton builder
13
- * (Daciuk et al., 2000) backed by typed arrays and an open-addressing state registry.
14
- */
15
- const buildGaddag = (words) => {
16
- const { charCodes, letterByCharCode } = buildAlphabet(words);
17
- const { itemsCount, wordBytes, wordOffsets, wordsCount } = encodeWords(words, letterByCharCode);
18
- const items = generateItems(wordsCount, wordOffsets, itemsCount);
19
- sortItems(items, wordBytes, wordOffsets);
20
- return insertItems(items, wordBytes, wordOffsets, charCodes);
21
- };
22
- exports.buildGaddag = buildGaddag;
23
- const buildAlphabet = (words) => {
24
- const codes = new Set();
25
- for (const word of words) {
26
- if (word.length > constants_1.MAX_WORD_LENGTH) {
27
- continue;
28
- }
29
- for (let index = 0; index < word.length; ++index) {
30
- codes.add(word.charCodeAt(index));
31
- }
32
- }
33
- if (codes.size > constants_1.MAX_LETTERS) {
34
- throw new Error(`Gaddag supports up to ${constants_1.MAX_LETTERS} distinct characters, got ${codes.size}`);
35
- }
36
- const charCodes = Int32Array.from([...codes].sort((a, b) => a - b));
37
- const letterByCharCode = new Map();
38
- for (let index = 0; index < charCodes.length; ++index) {
39
- letterByCharCode.set(charCodes[index], index + 1);
40
- }
41
- return { charCodes, letterByCharCode };
42
- };
43
- const encodeWords = (words, letterByCharCode) => {
44
- let totalLength = 0;
45
- let wordsCount = 0;
46
- for (const word of words) {
47
- if (word.length === 0 || word.length > constants_1.MAX_WORD_LENGTH) {
48
- continue;
49
- }
50
- totalLength += word.length;
51
- ++wordsCount;
52
- }
53
- if (wordsCount >= 1 << 25) {
54
- throw new Error('Gaddag supports up to 33M words');
55
- }
56
- const wordBytes = new Uint8Array(totalLength);
57
- const wordOffsets = new Int32Array(wordsCount + 1);
58
- let offset = 0;
59
- let wordIndex = 0;
60
- for (const word of words) {
61
- if (word.length === 0 || word.length > constants_1.MAX_WORD_LENGTH) {
62
- continue;
63
- }
64
- wordOffsets[wordIndex] = offset;
65
- for (let index = 0; index < word.length; ++index) {
66
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
- wordBytes[offset] = letterByCharCode.get(word.charCodeAt(index));
68
- ++offset;
69
- }
70
- ++wordIndex;
71
- }
72
- wordOffsets[wordsCount] = offset;
73
- return { itemsCount: totalLength, wordBytes, wordOffsets, wordsCount };
74
- };
75
- const generateItems = (wordsCount, wordOffsets, itemsCount) => {
76
- const items = new Int32Array(itemsCount);
77
- let itemIndex = 0;
78
- for (let wordIndex = 0; wordIndex < wordsCount; ++wordIndex) {
79
- const length = wordOffsets[wordIndex + 1] - wordOffsets[wordIndex];
80
- for (let split = 1; split <= length; ++split) {
81
- items[itemIndex] = (wordIndex << 6) | split;
82
- ++itemIndex;
83
- }
84
- }
85
- return items;
86
- };
87
- /**
88
- * Radix character of sequence `item` at position `depth`:
89
- * 0 = end of sequence, 1 = separator, letter + 1 otherwise.
90
- */
91
- const charAt = (item, depth, wordBytes, wordOffsets) => {
92
- const wordIndex = item >>> 6;
93
- const split = item & 63;
94
- const offset = wordOffsets[wordIndex];
95
- if (depth < split) {
96
- return wordBytes[offset + split - 1 - depth] + 1;
97
- }
98
- if (depth === split) {
99
- return split < wordOffsets[wordIndex + 1] - offset ? 1 : 0;
100
- }
101
- return depth <= wordOffsets[wordIndex + 1] - offset ? wordBytes[offset + depth - 1] + 1 : 0;
102
- };
103
- const RADIX = constants_1.MAX_LETTERS + 2;
104
- const sortItems = (items, wordBytes, wordOffsets) => {
105
- const auxiliary = new Int32Array(items.length);
106
- const counts = new Int32Array(RADIX);
107
- const starts = new Int32Array(RADIX);
108
- // Manual stack of (low, high, depth) ranges to avoid recursion.
109
- let stack = new Int32Array(3 * 64);
110
- let stackTop = 0;
111
- const push = (low, high, depth) => {
112
- if (stackTop + 3 > stack.length) {
113
- const grown = new Int32Array(stack.length * 2);
114
- grown.set(stack);
115
- stack = grown;
116
- }
117
- stack[stackTop] = low;
118
- stack[stackTop + 1] = high;
119
- stack[stackTop + 2] = depth;
120
- stackTop += 3;
121
- };
122
- push(0, items.length, 0);
123
- while (stackTop > 0) {
124
- stackTop -= 3;
125
- const low = stack[stackTop];
126
- const high = stack[stackTop + 1];
127
- let depth = stack[stackTop + 2];
128
- if (high - low < 2) {
129
- continue;
130
- }
131
- for (;;) {
132
- counts.fill(0);
133
- for (let index = low; index < high; ++index) {
134
- ++counts[charAt(items[index], depth, wordBytes, wordOffsets)];
135
- }
136
- // Skip scatter when the whole range shares the character at this depth.
137
- let singleBucket = -1;
138
- for (let bucket = 0; bucket < RADIX; ++bucket) {
139
- if (counts[bucket] === high - low) {
140
- singleBucket = bucket;
141
- break;
142
- }
143
- if (counts[bucket] > 0) {
144
- break;
145
- }
146
- }
147
- if (singleBucket > 0) {
148
- ++depth;
149
- continue;
150
- }
151
- if (singleBucket === 0) {
152
- break;
153
- }
154
- let position = low;
155
- for (let bucket = 0; bucket < RADIX; ++bucket) {
156
- starts[bucket] = position;
157
- position += counts[bucket];
158
- }
159
- for (let index = low; index < high; ++index) {
160
- const item = items[index];
161
- auxiliary[starts[charAt(item, depth, wordBytes, wordOffsets)]++] = item;
162
- }
163
- items.set(auxiliary.subarray(low, high), low);
164
- // After the scatter, starts[bucket] holds the end position of each bucket.
165
- for (let bucket = 1; bucket < RADIX; ++bucket) {
166
- if (counts[bucket] > 1) {
167
- push(starts[bucket] - counts[bucket], starts[bucket], depth + 1);
168
- }
169
- }
170
- break;
171
- }
172
- }
173
- };
174
- const MAX_DEPTH = constants_1.MAX_WORD_LENGTH + 2;
175
- const MAX_ARCS_PER_STATE = constants_1.MAX_LETTERS + 1;
176
- class Builder {
177
- constructor() {
178
- // Frozen arcs (1-indexed; index 0 is a sentinel).
179
- this.labels = new Uint8Array(1 << 20);
180
- this.targets = new Int32Array(1 << 20);
181
- this.arcTop = 1;
182
- // Open-addressing registry of frozen states, storing first-arc indices (0 = empty slot).
183
- this.table = new Int32Array(1 << 20);
184
- this.tableCount = 0;
185
- // Temporary (not yet minimized) states along the current insertion path.
186
- this.pathLetters = new Uint8Array(MAX_DEPTH * MAX_ARCS_PER_STATE);
187
- this.pathTargets = new Int32Array(MAX_DEPTH * MAX_ARCS_PER_STATE);
188
- this.pathCounts = new Int32Array(MAX_DEPTH);
189
- this.pathFinal = new Uint8Array(MAX_DEPTH);
190
- this.previous = new Uint8Array(MAX_DEPTH);
191
- this.previousLength = 0;
192
- }
193
- insert(sequence, length) {
194
- const { previous, pathCounts, pathFinal } = this;
195
- let commonPrefixLength = 0;
196
- const maxCommon = Math.min(length, this.previousLength);
197
- while (commonPrefixLength < maxCommon && sequence[commonPrefixLength] === previous[commonPrefixLength]) {
198
- ++commonPrefixLength;
199
- }
200
- if (commonPrefixLength === length && commonPrefixLength === this.previousLength) {
201
- return; // Duplicate sequence.
202
- }
203
- for (let depth = this.previousLength; depth > commonPrefixLength; --depth) {
204
- this.freeze(depth);
205
- }
206
- for (let depth = commonPrefixLength; depth < length; ++depth) {
207
- const base = depth * MAX_ARCS_PER_STATE;
208
- this.pathLetters[base + pathCounts[depth]] = sequence[depth];
209
- this.pathTargets[base + pathCounts[depth]] = 0;
210
- ++pathCounts[depth];
211
- pathCounts[depth + 1] = 0;
212
- pathFinal[depth + 1] = 0;
213
- }
214
- pathFinal[length] = 1;
215
- previous.set(sequence.subarray(0, length));
216
- this.previousLength = length;
217
- }
218
- finish(charCodes) {
219
- for (let depth = this.previousLength; depth > 0; --depth) {
220
- this.freeze(depth);
221
- }
222
- const rootRef = this.registerState(0);
223
- const labels = this.labels.slice(0, this.arcTop);
224
- const targets = this.targets.slice(0, this.arcTop);
225
- return new Gaddag_1.Gaddag(labels, targets, rootRef, charCodes);
226
- }
227
- /** Minimizes the state at `depth` and patches its parent's dangling arc. */
228
- freeze(depth) {
229
- const ref = this.registerState(depth);
230
- const parentBase = (depth - 1) * MAX_ARCS_PER_STATE;
231
- this.pathTargets[parentBase + this.pathCounts[depth - 1] - 1] = ref;
232
- }
233
- /** Returns the ref of a frozen state equivalent to the temporary state at `depth`. */
234
- registerState(depth) {
235
- const count = this.pathCounts[depth];
236
- const final = this.pathFinal[depth];
237
- if (count === 0) {
238
- return final;
239
- }
240
- const base = depth * MAX_ARCS_PER_STATE;
241
- const hash = this.hashPath(base, count);
242
- const mask = this.table.length - 1;
243
- let slot = hash & mask;
244
- for (;;) {
245
- const existing = this.table[slot];
246
- if (existing === 0) {
247
- break;
248
- }
249
- if (this.equalsPath(existing, base, count)) {
250
- return (existing << 1) | final;
251
- }
252
- slot = (slot + 1) & mask;
253
- }
254
- const firstArc = this.appendArcs(base, count);
255
- this.table[slot] = firstArc;
256
- ++this.tableCount;
257
- if (this.tableCount * 10 > this.table.length * 7) {
258
- this.growTable();
259
- }
260
- return (firstArc << 1) | final;
261
- }
262
- hashPath(base, count) {
263
- let hash = 0x811c9dc5 ^ count;
264
- for (let index = 0; index < count; ++index) {
265
- hash = Math.imul(hash ^ this.pathLetters[base + index], 16777619);
266
- hash = Math.imul(hash ^ this.pathTargets[base + index], 16777619);
267
- }
268
- return hash >>> 0;
269
- }
270
- hashFrozen(firstArc) {
271
- let count = 0;
272
- for (let index = firstArc;; ++index) {
273
- ++count;
274
- if (this.labels[index] >= constants_1.LAST_ARC_FLAG) {
275
- break;
276
- }
277
- }
278
- let hash = 0x811c9dc5 ^ count;
279
- for (let index = 0; index < count; ++index) {
280
- hash = Math.imul(hash ^ (this.labels[firstArc + index] & constants_1.LETTER_MASK), 16777619);
281
- hash = Math.imul(hash ^ this.targets[firstArc + index], 16777619);
282
- }
283
- return hash >>> 0;
284
- }
285
- equalsPath(firstArc, base, count) {
286
- for (let index = 0; index < count; ++index) {
287
- const label = this.labels[firstArc + index];
288
- if ((label & constants_1.LETTER_MASK) !== this.pathLetters[base + index]) {
289
- return false;
290
- }
291
- if (this.targets[firstArc + index] !== this.pathTargets[base + index]) {
292
- return false;
293
- }
294
- const isLast = label >= constants_1.LAST_ARC_FLAG;
295
- if (isLast !== (index === count - 1)) {
296
- return false;
297
- }
298
- }
299
- return true;
300
- }
301
- appendArcs(base, count) {
302
- if (this.arcTop + count > this.labels.length) {
303
- const capacity = Math.max(this.labels.length * 2, this.arcTop + count);
304
- const labels = new Uint8Array(capacity);
305
- labels.set(this.labels);
306
- this.labels = labels;
307
- const targets = new Int32Array(capacity);
308
- targets.set(this.targets);
309
- this.targets = targets;
310
- }
311
- const firstArc = this.arcTop;
312
- for (let index = 0; index < count; ++index) {
313
- this.labels[this.arcTop] = this.pathLetters[base + index] | (index === count - 1 ? constants_1.LAST_ARC_FLAG : 0);
314
- this.targets[this.arcTop] = this.pathTargets[base + index];
315
- ++this.arcTop;
316
- }
317
- return firstArc;
318
- }
319
- growTable() {
320
- const previousTable = this.table;
321
- this.table = new Int32Array(previousTable.length * 2);
322
- const mask = this.table.length - 1;
323
- for (const firstArc of previousTable) {
324
- if (firstArc === 0) {
325
- continue;
326
- }
327
- let slot = this.hashFrozen(firstArc) & mask;
328
- while (this.table[slot] !== 0) {
329
- slot = (slot + 1) & mask;
330
- }
331
- this.table[slot] = firstArc;
332
- }
333
- }
334
- }
335
- const insertItems = (items, wordBytes, wordOffsets, charCodes) => {
336
- const builder = new Builder();
337
- const sequence = new Uint8Array(MAX_DEPTH);
338
- for (let index = 0; index < items.length; ++index) {
339
- const item = items[index];
340
- const wordIndex = item >>> 6;
341
- const split = item & 63;
342
- const offset = wordOffsets[wordIndex];
343
- const length = wordOffsets[wordIndex + 1] - offset;
344
- let sequenceLength = 0;
345
- for (let position = split - 1; position >= 0; --position) {
346
- sequence[sequenceLength] = wordBytes[offset + position];
347
- ++sequenceLength;
348
- }
349
- if (split < length) {
350
- sequence[sequenceLength] = 0;
351
- ++sequenceLength;
352
- for (let position = split; position < length; ++position) {
353
- sequence[sequenceLength] = wordBytes[offset + position];
354
- ++sequenceLength;
355
- }
356
- }
357
- builder.insert(sequence, sequenceLength);
358
- }
359
- return builder.finish(charCodes);
360
- };
@@ -1,12 +0,0 @@
1
- /** Letter index reserved for the GADDAG separator (◇). */
2
- export declare const SEPARATOR = 0;
3
- /** Letters are stored on 6 bits (1..63); 0 is the separator. */
4
- export declare const MAX_LETTERS = 63;
5
- /** Words longer than this are skipped — they cannot fit on any board. */
6
- export declare const MAX_WORD_LENGTH = 63;
7
- /** Arc label bit marking the last arc of a state. */
8
- export declare const LAST_ARC_FLAG = 128;
9
- /** Mask extracting the letter from an arc label. */
10
- export declare const LETTER_MASK = 63;
11
- /** "GDG1" magic number opening the binary serialization format. */
12
- export declare const MAGIC = 826754119;
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAGIC = exports.LETTER_MASK = exports.LAST_ARC_FLAG = exports.MAX_WORD_LENGTH = exports.MAX_LETTERS = exports.SEPARATOR = void 0;
4
- /** Letter index reserved for the GADDAG separator (◇). */
5
- exports.SEPARATOR = 0;
6
- /** Letters are stored on 6 bits (1..63); 0 is the separator. */
7
- exports.MAX_LETTERS = 63;
8
- /** Words longer than this are skipped — they cannot fit on any board. */
9
- exports.MAX_WORD_LENGTH = 63;
10
- /** Arc label bit marking the last arc of a state. */
11
- exports.LAST_ARC_FLAG = 128;
12
- /** Mask extracting the letter from an arc label. */
13
- exports.LETTER_MASK = 63;
14
- /** "GDG1" magic number opening the binary serialization format. */
15
- exports.MAGIC = 0x31474447;
@@ -1,3 +0,0 @@
1
- export { buildGaddag } from './buildGaddag';
2
- export { LAST_ARC_FLAG, LETTER_MASK, MAX_LETTERS, MAX_WORD_LENGTH, SEPARATOR } from './constants';
3
- export { Gaddag } from './Gaddag';
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Gaddag = exports.SEPARATOR = exports.MAX_WORD_LENGTH = exports.MAX_LETTERS = exports.LETTER_MASK = exports.LAST_ARC_FLAG = exports.buildGaddag = void 0;
4
- var buildGaddag_1 = require("./buildGaddag");
5
- Object.defineProperty(exports, "buildGaddag", { enumerable: true, get: function () { return buildGaddag_1.buildGaddag; } });
6
- var constants_1 = require("./constants");
7
- Object.defineProperty(exports, "LAST_ARC_FLAG", { enumerable: true, get: function () { return constants_1.LAST_ARC_FLAG; } });
8
- Object.defineProperty(exports, "LETTER_MASK", { enumerable: true, get: function () { return constants_1.LETTER_MASK; } });
9
- Object.defineProperty(exports, "MAX_LETTERS", { enumerable: true, get: function () { return constants_1.MAX_LETTERS; } });
10
- Object.defineProperty(exports, "MAX_WORD_LENGTH", { enumerable: true, get: function () { return constants_1.MAX_WORD_LENGTH; } });
11
- Object.defineProperty(exports, "SEPARATOR", { enumerable: true, get: function () { return constants_1.SEPARATOR; } });
12
- var Gaddag_1 = require("./Gaddag");
13
- Object.defineProperty(exports, "Gaddag", { enumerable: true, get: function () { return Gaddag_1.Gaddag; } });