puzzle-lib 1.3.0 → 1.6.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 +21 -21
- package/README.md +38 -39
- package/build/src/Braille/BrailleCharacter.d.ts +15 -15
- package/build/src/Braille/BrailleCharacter.js +38 -37
- package/build/src/Braille/BrailleCharacter.js.map +1 -1
- package/build/src/Braille/BrailleData.d.ts +6 -6
- package/build/src/Braille/BrailleData.js +65 -64
- package/build/src/Braille/BrailleData.js.map +1 -1
- package/build/src/Braille/BrailleDot.d.ts +9 -9
- package/build/src/Braille/BrailleDot.js +13 -12
- package/build/src/Braille/BrailleDot.js.map +1 -1
- package/build/src/Braille/BrailleEncoding.d.ts +54 -54
- package/build/src/Braille/BrailleEncoding.js +65 -64
- package/build/src/Braille/BrailleEncoding.js.map +1 -1
- package/build/src/Braille/BrailleStream.d.ts +18 -18
- package/build/src/Braille/BrailleStream.js +75 -74
- package/build/src/Braille/BrailleStream.js.map +1 -1
- package/build/src/Cipher/AutoKeyString.d.ts +4 -4
- package/build/src/Cipher/AutoKeyString.js +34 -33
- package/build/src/Cipher/AutoKeyString.js.map +1 -1
- package/build/src/Cipher/CaesarString.d.ts +8 -8
- package/build/src/Cipher/CaesarString.js +31 -30
- package/build/src/Cipher/CaesarString.js.map +1 -1
- package/build/src/Cipher/CaesarUtils.d.ts +13 -13
- package/build/src/Cipher/CaesarUtils.js +57 -56
- package/build/src/Cipher/CaesarUtils.js.map +1 -1
- package/build/src/Cipher/KeyedCipherStringBase.d.ts +12 -12
- package/build/src/Cipher/KeyedCipherStringBase.js +28 -27
- package/build/src/Cipher/KeyedCipherStringBase.js.map +1 -1
- package/build/src/Cipher/VigenereString.d.ts +4 -4
- package/build/src/Cipher/VigenereString.js +21 -20
- package/build/src/Cipher/VigenereString.js.map +1 -1
- package/build/src/Common/CharacterImage.d.ts +6 -6
- package/build/src/Common/CharacterImage.js +10 -9
- package/build/src/Common/CharacterImage.js.map +1 -1
- package/build/src/Common/EncodingCategory.d.ts +8 -8
- package/build/src/Common/EncodingCategory.js +12 -11
- package/build/src/Common/EncodingCategory.js.map +1 -1
- package/build/src/Common/EncodingCharacterBase.d.ts +23 -23
- package/build/src/Common/EncodingCharacterBase.js +52 -51
- package/build/src/Common/EncodingCharacterBase.js.map +1 -1
- package/build/src/Common/EncodingDataBase.d.ts +7 -7
- package/build/src/Common/EncodingDataBase.js +29 -28
- package/build/src/Common/EncodingDataBase.js.map +1 -1
- package/build/src/Common/EncodingEntry.d.ts +8 -8
- package/build/src/Common/EncodingEntry.js +14 -13
- package/build/src/Common/EncodingEntry.js.map +1 -1
- package/build/src/Common/EncodingLookupResult.d.ts +6 -6
- package/build/src/Common/EncodingLookupResult.js +13 -12
- package/build/src/Common/EncodingLookupResult.js.map +1 -1
- package/build/src/Common/Helpers.d.ts +4 -4
- package/build/src/Common/Helpers.js +16 -15
- package/build/src/Common/Helpers.js.map +1 -1
- package/build/src/Common/InlineSvg.d.ts +7 -7
- package/build/src/Common/InlineSvg.js +14 -13
- package/build/src/Common/InlineSvg.js.map +1 -1
- package/build/src/Conversion/CharacterAutoConvert.d.ts +10 -7
- package/build/src/Conversion/CharacterAutoConvert.js +88 -80
- package/build/src/Conversion/CharacterAutoConvert.js.map +1 -1
- package/build/src/Conversion/CharacterConversion.d.ts +8 -8
- package/build/src/Conversion/CharacterConversion.js +50 -49
- package/build/src/Conversion/CharacterConversion.js.map +1 -1
- package/build/src/Conversion/CharacterEncoding.d.ts +9 -8
- package/build/src/Conversion/CharacterEncoding.js +13 -11
- package/build/src/Conversion/CharacterEncoding.js.map +1 -1
- package/build/src/Conversion/CharacterTableEntry.d.ts +10 -10
- package/build/src/Conversion/CharacterTableEntry.js +19 -18
- package/build/src/Conversion/CharacterTableEntry.js.map +1 -1
- package/build/src/Conversion/SignificantFigures.d.ts +7 -7
- package/build/src/Conversion/SignificantFigures.js +50 -49
- package/build/src/Conversion/SignificantFigures.js.map +1 -1
- package/build/src/Conversion/StringAutoConvert.d.ts +6 -6
- package/build/src/Conversion/StringAutoConvert.js +46 -45
- package/build/src/Conversion/StringAutoConvert.js.map +1 -1
- package/build/src/Morse/MorseCharacter.d.ts +22 -22
- package/build/src/Morse/MorseCharacter.js +96 -95
- package/build/src/Morse/MorseCharacter.js.map +1 -1
- package/build/src/Morse/MorseData.d.ts +6 -6
- package/build/src/Morse/MorseData.js +70 -69
- package/build/src/Morse/MorseData.js.map +1 -1
- package/build/src/Morse/MorseEncoding.d.ts +59 -59
- package/build/src/Morse/MorseEncoding.js +94 -93
- package/build/src/Morse/MorseEncoding.js.map +1 -1
- package/build/src/Morse/MorseString.d.ts +10 -10
- package/build/src/Morse/MorseString.js +66 -65
- package/build/src/Morse/MorseString.js.map +1 -1
- package/build/src/Nato/NatoCharacter.d.ts +5 -5
- package/build/src/Nato/NatoCharacter.js +10 -9
- package/build/src/Nato/NatoCharacter.js.map +1 -1
- package/build/src/Nato/NatoData.d.ts +7 -7
- package/build/src/Nato/NatoData.js +51 -50
- package/build/src/Nato/NatoData.js.map +1 -1
- package/build/src/NavalFlags/NavalFlags.d.ts +7 -7
- package/build/src/NavalFlags/NavalFlags.js +52 -50
- package/build/src/NavalFlags/NavalFlags.js.map +1 -1
- package/build/src/Resistor/Resistor.d.ts +24 -24
- package/build/src/Resistor/Resistor.js +86 -85
- package/build/src/Resistor/Resistor.js.map +1 -1
- package/build/src/Resistor/ResistorColorEntry.d.ts +12 -12
- package/build/src/Resistor/ResistorColorEntry.js +31 -30
- package/build/src/Resistor/ResistorColorEntry.js.map +1 -1
- package/build/src/Semaphore/SemaphoreCharacter.d.ts +20 -20
- package/build/src/Semaphore/SemaphoreCharacter.js +75 -74
- package/build/src/Semaphore/SemaphoreCharacter.js.map +1 -1
- package/build/src/Semaphore/SemaphoreData.d.ts +6 -6
- package/build/src/Semaphore/SemaphoreData.js +53 -52
- package/build/src/Semaphore/SemaphoreData.js.map +1 -1
- package/build/src/Semaphore/SemaphoreDegrees.d.ts +5 -5
- package/build/src/Semaphore/SemaphoreDegrees.js +26 -25
- package/build/src/Semaphore/SemaphoreDegrees.js.map +1 -1
- package/build/src/Semaphore/SemaphoreDirection.d.ts +11 -11
- package/build/src/Semaphore/SemaphoreDirection.js +15 -14
- package/build/src/Semaphore/SemaphoreDirection.js.map +1 -1
- package/build/src/Semaphore/SemaphoreEncoding.d.ts +40 -40
- package/build/src/Semaphore/SemaphoreEncoding.js +47 -46
- package/build/src/Semaphore/SemaphoreEncoding.js.map +1 -1
- package/build/src/Semaphore/SemaphoreStream.d.ts +17 -17
- package/build/src/Semaphore/SemaphoreStream.js +72 -71
- package/build/src/Semaphore/SemaphoreStream.js.map +1 -1
- package/build/src/WordSearch/Point.d.ts +4 -4
- package/build/src/WordSearch/Point.js +2 -2
- package/build/src/WordSearch/Result.d.ts +6 -6
- package/build/src/WordSearch/Result.js +10 -9
- package/build/src/WordSearch/Result.js.map +1 -1
- package/build/src/WordSearch/WordSearchDirection.d.ts +6 -6
- package/build/src/WordSearch/WordSearchDirection.js +10 -9
- package/build/src/WordSearch/WordSearchDirection.js.map +1 -1
- package/build/src/WordSearch/WordSearchSolver.d.ts +27 -18
- package/build/src/WordSearch/WordSearchSolver.js +222 -171
- package/build/src/WordSearch/WordSearchSolver.js.map +1 -1
- package/build/src/index.d.ts +35 -35
- package/build/src/index.js +72 -70
- package/build/src/index.js.map +1 -1
- package/package.json +40 -39
- package/src/Braille/BrailleCharacter.ts +49 -0
- package/src/Braille/BrailleData.ts +131 -0
- package/src/Braille/BrailleDot.ts +9 -0
- package/src/Braille/BrailleEncoding.ts +144 -0
- package/src/Braille/BrailleStream.ts +87 -0
- package/src/Cipher/AutoKeyString.ts +35 -0
- package/src/Cipher/CaesarString.ts +38 -0
- package/src/Cipher/CaesarUtils.ts +69 -0
- package/src/Cipher/KeyedCipherStringBase.ts +35 -0
- package/src/Cipher/VigenereString.ts +21 -0
- package/src/Common/CharacterImage.ts +11 -0
- package/src/Common/EncodingCategory.ts +10 -0
- package/src/Common/EncodingCharacterBase.ts +72 -0
- package/src/Common/EncodingDataBase.ts +31 -0
- package/src/Common/EncodingEntry.ts +17 -0
- package/src/Common/EncodingLookupResult.ts +10 -0
- package/src/Common/Helpers.ts +13 -0
- package/src/Common/InlineSvg.ts +15 -0
- package/src/Conversion/CharacterAutoConvert.ts +108 -0
- package/src/Conversion/CharacterConversion.ts +89 -0
- package/src/Conversion/CharacterEncoding.ts +9 -0
- package/src/Conversion/CharacterTableEntry.ts +23 -0
- package/src/Conversion/SignificantFigures.ts +55 -0
- package/src/Conversion/StringAutoConvert.ts +56 -0
- package/src/Morse/MorseCharacter.ts +112 -0
- package/src/Morse/MorseData.ts +143 -0
- package/src/Morse/MorseEncoding.ts +98 -0
- package/src/Morse/MorseString.ts +106 -0
- package/src/Nato/NatoCharacter.ts +9 -0
- package/src/Nato/NatoData.ts +49 -0
- package/src/NavalFlags/LICENSE +7 -0
- package/src/NavalFlags/NavalFlags.ts +293 -0
- package/src/Resistor/Resistor.ts +135 -0
- package/src/Resistor/ResistorColorEntry.ts +43 -0
- package/src/Semaphore/SemaphoreCharacter.ts +107 -0
- package/src/Semaphore/SemaphoreData.ts +58 -0
- package/src/Semaphore/SemaphoreDegrees.ts +26 -0
- package/src/Semaphore/SemaphoreDirection.ts +11 -0
- package/src/Semaphore/SemaphoreEncoding.ts +48 -0
- package/src/Semaphore/SemaphoreStream.ts +89 -0
- package/src/WordSearch/Point.ts +4 -0
- package/src/WordSearch/Result.ts +10 -0
- package/src/WordSearch/WordSearchDirection.ts +6 -0
- package/src/WordSearch/WordSearchSolver.ts +271 -0
- package/src/index.ts +38 -0
- package/src/trie-prefix-tree.d.ts +70 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {SemaphoreDirection} from './SemaphoreDirection';
|
|
2
|
+
|
|
3
|
+
export enum SemaphoreEncoding {
|
|
4
|
+
None = 0,
|
|
5
|
+
|
|
6
|
+
// Letters
|
|
7
|
+
LetterA = SemaphoreDirection.SouthWest | SemaphoreDirection.South,
|
|
8
|
+
LetterB = SemaphoreDirection.West | SemaphoreDirection.South,
|
|
9
|
+
LetterC = SemaphoreDirection.NorthWest | SemaphoreDirection.South,
|
|
10
|
+
LetterD = SemaphoreDirection.North | SemaphoreDirection.South,
|
|
11
|
+
LetterE = SemaphoreDirection.NorthEast | SemaphoreDirection.South,
|
|
12
|
+
LetterF = SemaphoreDirection.East | SemaphoreDirection.South,
|
|
13
|
+
LetterG = SemaphoreDirection.SouthEast | SemaphoreDirection.South,
|
|
14
|
+
LetterH = SemaphoreDirection.SouthWest | SemaphoreDirection.West,
|
|
15
|
+
LetterI = SemaphoreDirection.SouthWest | SemaphoreDirection.NorthWest,
|
|
16
|
+
LetterJ = SemaphoreDirection.North | SemaphoreDirection.East,
|
|
17
|
+
LetterK = SemaphoreDirection.SouthWest | SemaphoreDirection.North,
|
|
18
|
+
LetterL = SemaphoreDirection.SouthWest | SemaphoreDirection.NorthEast,
|
|
19
|
+
LetterM = SemaphoreDirection.SouthWest | SemaphoreDirection.East,
|
|
20
|
+
LetterN = SemaphoreDirection.SouthWest | SemaphoreDirection.SouthEast,
|
|
21
|
+
LetterO = SemaphoreDirection.West | SemaphoreDirection.NorthWest,
|
|
22
|
+
LetterP = SemaphoreDirection.West | SemaphoreDirection.North,
|
|
23
|
+
LetterQ = SemaphoreDirection.West | SemaphoreDirection.NorthEast,
|
|
24
|
+
LetterR = SemaphoreDirection.West | SemaphoreDirection.East,
|
|
25
|
+
LetterS = SemaphoreDirection.West | SemaphoreDirection.SouthEast,
|
|
26
|
+
LetterT = SemaphoreDirection.NorthWest | SemaphoreDirection.North,
|
|
27
|
+
LetterU = SemaphoreDirection.NorthWest | SemaphoreDirection.NorthEast,
|
|
28
|
+
LetterV = SemaphoreDirection.North | SemaphoreDirection.SouthEast,
|
|
29
|
+
LetterW = SemaphoreDirection.East | SemaphoreDirection.NorthEast,
|
|
30
|
+
LetterX = SemaphoreDirection.SouthEast | SemaphoreDirection.NorthEast,
|
|
31
|
+
LetterY = SemaphoreDirection.NorthWest | SemaphoreDirection.East,
|
|
32
|
+
LetterZ = SemaphoreDirection.SouthEast | SemaphoreDirection.East,
|
|
33
|
+
|
|
34
|
+
// Numbers
|
|
35
|
+
Number1 = SemaphoreDirection.SouthWest | SemaphoreDirection.South,
|
|
36
|
+
Number2 = SemaphoreDirection.West | SemaphoreDirection.South,
|
|
37
|
+
Number3 = SemaphoreDirection.NorthWest | SemaphoreDirection.South,
|
|
38
|
+
Number4 = SemaphoreDirection.North | SemaphoreDirection.South,
|
|
39
|
+
Number5 = SemaphoreDirection.NorthEast | SemaphoreDirection.South,
|
|
40
|
+
Number6 = SemaphoreDirection.East | SemaphoreDirection.South,
|
|
41
|
+
Number7 = SemaphoreDirection.SouthEast | SemaphoreDirection.South,
|
|
42
|
+
Number8 = SemaphoreDirection.SouthWest | SemaphoreDirection.West,
|
|
43
|
+
Number9 = SemaphoreDirection.SouthWest | SemaphoreDirection.NorthWest,
|
|
44
|
+
Number0 = SemaphoreDirection.SouthWest | SemaphoreDirection.North,
|
|
45
|
+
|
|
46
|
+
// Formatting
|
|
47
|
+
FormattingNumber = SemaphoreDirection.North | SemaphoreDirection.NorthEast,
|
|
48
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {EncodingCategory} from '../Common/EncodingCategory';
|
|
2
|
+
import {SemaphoreCharacter} from './SemaphoreCharacter';
|
|
3
|
+
import {SemaphoreData} from './SemaphoreData';
|
|
4
|
+
import {SemaphoreEncoding} from './SemaphoreEncoding';
|
|
5
|
+
|
|
6
|
+
interface SemaphoreStreamState {
|
|
7
|
+
numberMode: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class SemaphoreStream {
|
|
11
|
+
private readonly _chars: SemaphoreEncoding[] = [];
|
|
12
|
+
private readonly _state: SemaphoreStreamState;
|
|
13
|
+
private _currentStr = '';
|
|
14
|
+
private _processPosition = 0;
|
|
15
|
+
|
|
16
|
+
constructor(chars?: SemaphoreEncoding[]) {
|
|
17
|
+
if (chars) {
|
|
18
|
+
this._chars = Array.from(chars);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
this._state = {
|
|
22
|
+
numberMode: false,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
this.invalidate();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get chars() {
|
|
29
|
+
return this._chars;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set chars(value: SemaphoreEncoding[]) {
|
|
33
|
+
this.clear();
|
|
34
|
+
|
|
35
|
+
for (const ch of value) {
|
|
36
|
+
this._chars.push(ch);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
append(ch: SemaphoreCharacter) {
|
|
41
|
+
this._chars.push(ch.valueOf());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
clear() {
|
|
45
|
+
this._chars.length = 0;
|
|
46
|
+
this.invalidate();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
space() {
|
|
50
|
+
this._chars.push(SemaphoreEncoding.None);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
toString() {
|
|
54
|
+
this.update();
|
|
55
|
+
return this._currentStr;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private invalidate() {
|
|
59
|
+
this._currentStr = '';
|
|
60
|
+
this._processPosition = 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private update() {
|
|
64
|
+
while (this._processPosition < this._chars.length) {
|
|
65
|
+
const ch = this._chars[this._processPosition];
|
|
66
|
+
|
|
67
|
+
if (ch === SemaphoreEncoding.None) {
|
|
68
|
+
this._state.numberMode = false;
|
|
69
|
+
this._currentStr += ' ';
|
|
70
|
+
} else if (ch === SemaphoreEncoding.FormattingNumber) {
|
|
71
|
+
this._state.numberMode = true;
|
|
72
|
+
this._currentStr += '#';
|
|
73
|
+
} else {
|
|
74
|
+
const category =
|
|
75
|
+
EncodingCategory.Punctuation |
|
|
76
|
+
(this._state.numberMode
|
|
77
|
+
? EncodingCategory.Number
|
|
78
|
+
: EncodingCategory.Letter);
|
|
79
|
+
const exact = SemaphoreData.instance.lookup(ch, category).exact;
|
|
80
|
+
|
|
81
|
+
if (exact.length > 0) {
|
|
82
|
+
this._currentStr += exact[0].toString();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this._processPosition++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import trie = require('trie-prefix-tree');
|
|
2
|
+
|
|
3
|
+
import {Point} from './Point';
|
|
4
|
+
import {Result} from './Result';
|
|
5
|
+
import {WordSearchDirection} from './WordSearchDirection';
|
|
6
|
+
|
|
7
|
+
export enum WordSearchSpaceTreatment {
|
|
8
|
+
None = 0,
|
|
9
|
+
RemoveWithinPuzzle = 1,
|
|
10
|
+
RemoveAll = 2,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class WordSearchSolver {
|
|
14
|
+
// The grid of letters which makes up the wordsearch puzzle
|
|
15
|
+
private _matrix: string[][];
|
|
16
|
+
// Transpositions to apply when finding words
|
|
17
|
+
private _directions: number[][];
|
|
18
|
+
// Potential words to find in the letter grid
|
|
19
|
+
private _targets: ReturnType<typeof trie>;
|
|
20
|
+
// Should we search for words not following a line
|
|
21
|
+
private _canBend: boolean;
|
|
22
|
+
// What should we do with spaces
|
|
23
|
+
private _spaceTreatment: WordSearchSpaceTreatment;
|
|
24
|
+
|
|
25
|
+
constructor() {
|
|
26
|
+
// Use empty grid and list by default
|
|
27
|
+
this._matrix = [[]];
|
|
28
|
+
this._targets = trie([]);
|
|
29
|
+
// Use both sets of directions by default
|
|
30
|
+
this._directions = [
|
|
31
|
+
// Cardinal directions
|
|
32
|
+
[0, 1],
|
|
33
|
+
[-1, 0],
|
|
34
|
+
[1, 0],
|
|
35
|
+
[0, -1],
|
|
36
|
+
// Diagonal
|
|
37
|
+
[1, 1],
|
|
38
|
+
[-1, -1],
|
|
39
|
+
[1, -1],
|
|
40
|
+
[-1, 1],
|
|
41
|
+
];
|
|
42
|
+
this._canBend = false;
|
|
43
|
+
this._spaceTreatment = WordSearchSpaceTreatment.None;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setWords(words: string[]) {
|
|
47
|
+
this._targets = trie([]);
|
|
48
|
+
for (const full of words) {
|
|
49
|
+
if (full === null || typeof full === 'undefined') {
|
|
50
|
+
throw new Error('Invalid input in WordSearchSolver.findWords()');
|
|
51
|
+
}
|
|
52
|
+
const word = full.trim();
|
|
53
|
+
if (word !== '') {
|
|
54
|
+
this._targets.addWord(word);
|
|
55
|
+
} else {
|
|
56
|
+
throw new Error('Cannot find an empty string in the wordsearch');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
parseGrid(gridInputText: string) {
|
|
62
|
+
const lines = gridInputText.split(/\r?\n/);
|
|
63
|
+
const grid: string[][] = [];
|
|
64
|
+
for (const line of lines) {
|
|
65
|
+
grid.push(line.split(''));
|
|
66
|
+
}
|
|
67
|
+
this.setGrid(grid);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
setGrid(matrix: string[][]) {
|
|
71
|
+
this._matrix = matrix;
|
|
72
|
+
this.checkSpaces();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setDirections(direction: WordSearchDirection) {
|
|
76
|
+
this._directions = [];
|
|
77
|
+
if (
|
|
78
|
+
direction === WordSearchDirection.Cardinal ||
|
|
79
|
+
direction === WordSearchDirection.CardinalAndDiagonal
|
|
80
|
+
) {
|
|
81
|
+
this._directions = this._directions.concat([
|
|
82
|
+
[0, 1],
|
|
83
|
+
[-1, 0],
|
|
84
|
+
[1, 0],
|
|
85
|
+
[0, -1],
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
if (
|
|
89
|
+
direction === WordSearchDirection.Diagonal ||
|
|
90
|
+
direction === WordSearchDirection.CardinalAndDiagonal
|
|
91
|
+
) {
|
|
92
|
+
this._directions = this._directions.concat([
|
|
93
|
+
[1, 1],
|
|
94
|
+
[-1, -1],
|
|
95
|
+
[1, -1],
|
|
96
|
+
[-1, 1],
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setSpaceTreatment(treatment: WordSearchSpaceTreatment) {
|
|
102
|
+
this._spaceTreatment = treatment;
|
|
103
|
+
|
|
104
|
+
if (this._matrix.length > 0) {
|
|
105
|
+
this.checkSpaces();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
setCanBend(canBend: boolean) {
|
|
110
|
+
this._canBend = canBend;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
findWords(): Result[] {
|
|
114
|
+
const results: Result[] = [];
|
|
115
|
+
const numRows = this._matrix.length;
|
|
116
|
+
for (let yIdx = 0; yIdx < numRows; yIdx++) {
|
|
117
|
+
const lineLength = this._matrix[yIdx].length;
|
|
118
|
+
for (let xIdx = 0; xIdx < lineLength; xIdx++) {
|
|
119
|
+
const p: Point = {x: xIdx, y: yIdx};
|
|
120
|
+
const pointResults = this.search(p);
|
|
121
|
+
results.push(...pointResults);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private search(start: Point): Result[] {
|
|
128
|
+
const results: Result[] = [];
|
|
129
|
+
if (this._canBend) {
|
|
130
|
+
const history: Point[] = [];
|
|
131
|
+
const dfsResults = this.dfsCheck(start, new Set(), history);
|
|
132
|
+
results.push(...dfsResults);
|
|
133
|
+
} else {
|
|
134
|
+
for (const translation of this._directions) {
|
|
135
|
+
const directionalResults = this.lineCheck(start, translation);
|
|
136
|
+
results.push(...directionalResults);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return results;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private dfsCheck(
|
|
143
|
+
start: Point,
|
|
144
|
+
visited: Set<Point>,
|
|
145
|
+
history: Point[]
|
|
146
|
+
): Result[] {
|
|
147
|
+
const results: Result[] = [];
|
|
148
|
+
|
|
149
|
+
if (visited.has(start)) {
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
visited.add(start);
|
|
154
|
+
history.push(start);
|
|
155
|
+
|
|
156
|
+
let currentString = '';
|
|
157
|
+
|
|
158
|
+
for (let i = 0; i < history.length; i++) {
|
|
159
|
+
const pt = history[i];
|
|
160
|
+
currentString = currentString + this._matrix[pt.y][pt.x];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const wordsWithPrefix = this._targets.getPrefix(currentString);
|
|
164
|
+
if (wordsWithPrefix.length === 0) {
|
|
165
|
+
visited.delete(start);
|
|
166
|
+
history.pop();
|
|
167
|
+
return results;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (wordsWithPrefix.indexOf(currentString) !== -1) {
|
|
171
|
+
const foundWord = new Result(currentString, history);
|
|
172
|
+
results.push(foundWord);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
for (const translation of this._directions) {
|
|
176
|
+
const next: Point = {
|
|
177
|
+
x: start.x + translation[0],
|
|
178
|
+
y: start.y + translation[1],
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
if (this.isInBounds(next)) {
|
|
182
|
+
results.push(...this.dfsCheck(next, visited, history));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
visited.delete(start);
|
|
187
|
+
history.pop();
|
|
188
|
+
|
|
189
|
+
return results;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private lineCheck(start: Point, direction: number[]): Result[] {
|
|
193
|
+
const results: Result[] = [];
|
|
194
|
+
|
|
195
|
+
// Working set
|
|
196
|
+
let currentPoint = start;
|
|
197
|
+
let currentString = '';
|
|
198
|
+
const pointHistory = [];
|
|
199
|
+
while (this.isInBounds(currentPoint)) {
|
|
200
|
+
currentString =
|
|
201
|
+
currentString + this._matrix[currentPoint.y][currentPoint.x];
|
|
202
|
+
|
|
203
|
+
// Get the candidates with the current prefix string
|
|
204
|
+
const wordsWithPrefix = this._targets.getPrefix(currentString);
|
|
205
|
+
|
|
206
|
+
// No point in going on, we've run out of possibilities
|
|
207
|
+
if (wordsWithPrefix.length === 0) {
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const p: Point = {x: currentPoint.x, y: currentPoint.y};
|
|
212
|
+
pointHistory.push(p);
|
|
213
|
+
|
|
214
|
+
// Is a candidate an exact match for the current search string? Save it.
|
|
215
|
+
if (wordsWithPrefix.indexOf(currentString) !== -1) {
|
|
216
|
+
const foundWord = new Result(currentString, pointHistory);
|
|
217
|
+
results.push(foundWord);
|
|
218
|
+
}
|
|
219
|
+
const next: Point = {
|
|
220
|
+
x: currentPoint.x + direction[0],
|
|
221
|
+
y: currentPoint.y + direction[1],
|
|
222
|
+
};
|
|
223
|
+
currentPoint = next;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return results;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private isInBounds(point: Point): boolean {
|
|
230
|
+
if (point.y < 0 || point.y >= this._matrix.length) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
if (point.x < 0 || point.x >= this._matrix[point.y].length) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private checkSpaces(): void {
|
|
240
|
+
if (
|
|
241
|
+
this._matrix.length === 0 ||
|
|
242
|
+
this._spaceTreatment === WordSearchSpaceTreatment.None
|
|
243
|
+
) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const nextMatrix = [];
|
|
248
|
+
for (let yIdx = 0; yIdx < this._matrix.length; yIdx++) {
|
|
249
|
+
const line = [];
|
|
250
|
+
let inPuzzle = false;
|
|
251
|
+
for (let xIdx = 0; xIdx < this._matrix[yIdx].length; xIdx++) {
|
|
252
|
+
const letter = this._matrix[yIdx][xIdx];
|
|
253
|
+
if (letter !== ' ') {
|
|
254
|
+
inPuzzle = true;
|
|
255
|
+
}
|
|
256
|
+
if (
|
|
257
|
+
this._spaceTreatment === WordSearchSpaceTreatment.RemoveAll &&
|
|
258
|
+
letter !== ' '
|
|
259
|
+
) {
|
|
260
|
+
line.push(this._matrix[yIdx][xIdx]);
|
|
261
|
+
} else if (letter !== ' ' && inPuzzle) {
|
|
262
|
+
line.push(this._matrix[yIdx][xIdx]);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (line.length > 0) {
|
|
266
|
+
nextMatrix.push(line);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
this._matrix = nextMatrix;
|
|
270
|
+
}
|
|
271
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export {BrailleCharacter} from './Braille/BrailleCharacter';
|
|
2
|
+
export {BrailleDot} from './Braille/BrailleDot';
|
|
3
|
+
export {BrailleEncoding} from './Braille/BrailleEncoding';
|
|
4
|
+
export {BrailleStream} from './Braille/BrailleStream';
|
|
5
|
+
export {AutoKeyString} from './Cipher/AutoKeyString';
|
|
6
|
+
export {CaesarString} from './Cipher/CaesarString';
|
|
7
|
+
export {KeyedCipherStringBase} from './Cipher/KeyedCipherStringBase';
|
|
8
|
+
export {VigenereString} from './Cipher/VigenereString';
|
|
9
|
+
export {CharacterImage} from './Common/CharacterImage';
|
|
10
|
+
export {EncodingCategory} from './Common/EncodingCategory';
|
|
11
|
+
export {EncodingEntry} from './Common/EncodingEntry';
|
|
12
|
+
export {InlineSvg} from './Common/InlineSvg';
|
|
13
|
+
export {CharacterAutoConvert} from './Conversion/CharacterAutoConvert';
|
|
14
|
+
export {CharacterConversion} from './Conversion/CharacterConversion';
|
|
15
|
+
export {CharacterEncoding} from './Conversion/CharacterEncoding';
|
|
16
|
+
export {CharacterTableEntry} from './Conversion/CharacterTableEntry';
|
|
17
|
+
export {SignificantFigures} from './Conversion/SignificantFigures';
|
|
18
|
+
export {StringAutoConvert} from './Conversion/StringAutoConvert';
|
|
19
|
+
export {MorseCharacter} from './Morse/MorseCharacter';
|
|
20
|
+
export {MorseEncoding} from './Morse/MorseEncoding';
|
|
21
|
+
export {MorseString} from './Morse/MorseString';
|
|
22
|
+
export {NatoCharacter} from './Nato/NatoCharacter';
|
|
23
|
+
export {NatoData} from './Nato/NatoData';
|
|
24
|
+
export {NavalFlags} from './NavalFlags/NavalFlags';
|
|
25
|
+
export {Resistor} from './Resistor/Resistor';
|
|
26
|
+
export {ResistorColorEntry} from './Resistor/ResistorColorEntry';
|
|
27
|
+
export {SemaphoreCharacter} from './Semaphore/SemaphoreCharacter';
|
|
28
|
+
export {SemaphoreDegrees} from './Semaphore/SemaphoreDegrees';
|
|
29
|
+
export {SemaphoreDirection} from './Semaphore/SemaphoreDirection';
|
|
30
|
+
export {SemaphoreEncoding} from './Semaphore/SemaphoreEncoding';
|
|
31
|
+
export {SemaphoreStream} from './Semaphore/SemaphoreStream';
|
|
32
|
+
export {Point as WordSearchPoint} from './WordSearch/Point';
|
|
33
|
+
export {Result as WordSearchResult} from './WordSearch/Result';
|
|
34
|
+
export {WordSearchDirection} from './WordSearch/WordSearchDirection';
|
|
35
|
+
export {
|
|
36
|
+
WordSearchSolver,
|
|
37
|
+
WordSearchSpaceTreatment,
|
|
38
|
+
} from './WordSearch/WordSearchSolver';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Type definitions for trie-prefix-tree 1.5
|
|
2
|
+
// Project: https://github.com/lyndseybrowning/trie-prefix#readme
|
|
3
|
+
// Definitions by: James Lismore <https://github.com/jlismore>
|
|
4
|
+
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
5
|
+
// TypeScript Version: 2.8
|
|
6
|
+
|
|
7
|
+
// The published typings don't seem to work correctly with ES6 module syntax,
|
|
8
|
+
// switch to CommonJS module syntax instead.
|
|
9
|
+
declare module 'trie-prefix-tree' {
|
|
10
|
+
function Trie(strings: string[]): {
|
|
11
|
+
/**
|
|
12
|
+
* Get a string representation of the trie
|
|
13
|
+
*/
|
|
14
|
+
dump(spacer?: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* Get the generated raw trie object
|
|
17
|
+
*/
|
|
18
|
+
tree(): {};
|
|
19
|
+
/**
|
|
20
|
+
* Add a new word to the trie
|
|
21
|
+
*/
|
|
22
|
+
addWord(word: string): ReturnType<typeof Trie>;
|
|
23
|
+
/**
|
|
24
|
+
* Remove an existing word from the trie
|
|
25
|
+
*/
|
|
26
|
+
removeWord(word: string): ReturnType<typeof Trie>;
|
|
27
|
+
/**
|
|
28
|
+
* Check a prefix is valid
|
|
29
|
+
* @returns Boolean
|
|
30
|
+
*/
|
|
31
|
+
isPrefix(word: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Count the number of words with the given prefixSearch
|
|
34
|
+
* @returns Number
|
|
35
|
+
*/
|
|
36
|
+
countPrefix(word: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Get a list of all words in the trie with the given prefix
|
|
39
|
+
* @returns Array
|
|
40
|
+
*/
|
|
41
|
+
getPrefix(word: string, sort?: boolean): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Get a random word in the trie with the given prefix
|
|
44
|
+
* @returns Array
|
|
45
|
+
*/
|
|
46
|
+
getRandomWordWithPrefix(prefix: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Get all words in the trie
|
|
49
|
+
* @returns Array
|
|
50
|
+
*/
|
|
51
|
+
getWords(sorted?: boolean): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Check the existence of a word in the trie
|
|
54
|
+
* @returns Boolean
|
|
55
|
+
*/
|
|
56
|
+
hasWord(word: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Get a list of valid anagrams that can be made from the given letters
|
|
59
|
+
* @returns Array
|
|
60
|
+
*/
|
|
61
|
+
getAnagrams(word: string): string[];
|
|
62
|
+
/**
|
|
63
|
+
* Get a list of all sub-anagrams that can be made from the given letters
|
|
64
|
+
* @returns Array
|
|
65
|
+
*/
|
|
66
|
+
getSubAnagrams(word: string): string[];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export = Trie;
|
|
70
|
+
}
|