Reword word lookup algorith to use bisection, get rid of index file.

pull/1662/head
marko 2022-04-06 17:30:12 -04:00
parent 4edfcc6d00
commit f7b2ece533
6 changed files with 21 additions and 74617 deletions

View File

@ -1,2 +1,3 @@
0.01: New app!
0.02: Fix bug with regenerating index, fix bug in word lookups
0.03: Improve word search performance

View File

@ -27,10 +27,7 @@ least once and yields an additional 7 points. Each game contains at least one pa
The game uses an internal dictionary consisting of a newline separated list of English words ('bee.words', using the '2of12inf' word list).
The dictionary is fairly large (~700kB of flash space) and thus requires appropriate space on the watch and will make installing the app somewhat
slow. Because of its size it cannot be compressed (heatshrink needs to hold the compressed/uncompressed data in memory).
In order to make checking the validity of a guessed word faster an index file ('bee_lindex.json') is installed with
the app that facilitates faster word lookups. This index file is specific to the dictionary file used. If one were to
replace the dictionary file with a different version (e.g. a different language) the index file has to be regenerated. The easiest
way to do so is to delete (via the Web IDE or the fileman app on the watch) the file 'bee_lindex.json' - it will be regenerated (and saved,
i.e. it only happens once) on app startup automatically, a process that takes roughly 30 seconds.
This file can be replaced with a custom dictionary, an ASCII file containing a newline-separated (single "\n", not DOS-style "\r\n") alphabetically
sorted (sorting is important for the word lookup algorithm) list of words.
![Screenshot](./bee_screenshot.png)

View File

@ -1,7 +1,7 @@
const S = require("Storage");
const words = S.read("bee.words");
var letters = [];
var letterIdx = [];
var centers = [];
@ -12,29 +12,17 @@ var score = 0;
var intervalID = -1;
function prepareLetterIdx () {
function biSearch(w, ws, start, end, count) {
"compile"
var li = [0];
if (S.read("bee_lindex.json")!==undefined) li = S.readJSON("bee_lindex.json"); // check for cached index
else {
for (var i=1; i<26; ++i) {
var prefix = String.fromCharCode(97+i%26);
console.log(prefix);
li.push(S.read('bee.words').indexOf("\n"+prefix, li[i-1])+1);
}
li.push(S.read('bee.words').length);
S.writeJSON("bee_lindex.json", li);
}
for (var i=0; i<26; ++i) letterIdx[i] = S.read("bee.words", li[i], li[i+1]-li[i]);
}
function findWord (w) {
"compile"
var ci = w.charCodeAt(0)-97;
var f = letterIdx[ci].indexOf("\n"+w+"\n");
if (f>=0) return true;
if (letterIdx[ci].substr(0, w.length)==w) return true;
return false;
if (start>end-w.legnth || count--<=0) return ws.substr(start, end-start).indexOf("\n"+w+"\n");
var mid = (end+start)>>1;
if (ws[mid-1]==="\n") --mid;
else while (mid<end && ws[mid]!=="\n") mid++;
var i = 0;
while (i<w.length && ws[mid+i+1]==w[i]) ++i;
if (i==w.length && ws[mid+i+1]==="\n") return mid+1;
if (i==w.length || w[i]<ws[mid+i+1]) return biSearch(w, ws, start, mid+1, count);
if (w[i]>ws[mid+i+1]) return biSearch(w, ws, mid+1, end, count);
}
function isPangram(w) {
@ -46,7 +34,7 @@ function isPangram(w) {
function checkWord (w) {
if (w.indexOf(String.fromCharCode(97+letters[0]))==-1) return false; // does it contain central letter?
if (foundWords.indexOf(w)>=0) return false; // already found
if (findWord(w)) {
if (biSearch(w, words, 0, words.length, 20)>-1) {
foundWords.push(w);
foundWords.sort();
if (w.length==4) score++;
@ -93,13 +81,12 @@ function pickLetters() {
var ltrs = "";
while (ltrs.length!==7) {
ltrs = [];
var j = Math.floor(26*Math.random());
var i = Math.floor((letterIdx[j].length-10)*Math.random());
while (letterIdx[j][i]!="\n" && i<letterIdx[j].length) ++i;
if (i<letterIdx[j].length-1) {
var i = Math.floor((words.length-10)*Math.random());
while (words[i]!="\n" && i<words.length) ++i;
if (i<words.length-1) {
++i;
while (letterIdx[j][i]!=="\n") {
var c = letterIdx[j][i];
while (words[i]!=="\n") {
var c = words[i];
if (ltrs.indexOf(c)===-1) ltrs += c;
++i;
}
@ -187,7 +174,6 @@ function showWordList() {
});
}
prepareLetterIdx();
pickLetters();
drawHive();
drawScore();

View File

@ -1 +0,0 @@
[0,41048,80445,152390,198606,228714,257919,279071,303726,337982,343582,348026,367246,404452,419780,438696,496250,499697,544600,624304,659085,680996,691270,708186,708341,709916,710883]

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
"name": "Bee",
"shortName":"Bee",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "Spelling bee",
"supports" : ["BANGLEJS2"],
"readme": "README.md",
@ -10,7 +10,6 @@
"storage": [
{"name":"bee.app.js","url":"bee.app.js"},
{"name":"bee.words","url":"bee_words_2of12"},
{"name":"bee_lindex.json","url":"bee_lindex.json"},
{"name":"bee.img","url":"app-icon.js","evaluate":true}
]
}