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.01: New app!
0.02: Fix bug with regenerating index, fix bug in word lookups 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 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 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). 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 This file can be replaced with a custom dictionary, an ASCII file containing a newline-separated (single "\n", not DOS-style "\r\n") alphabetically
the app that facilitates faster word lookups. This index file is specific to the dictionary file used. If one were to sorted (sorting is important for the word lookup algorithm) list of words.
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.
![Screenshot](./bee_screenshot.png) ![Screenshot](./bee_screenshot.png)

View File

@ -1,7 +1,7 @@
const S = require("Storage"); const S = require("Storage");
const words = S.read("bee.words");
var letters = []; var letters = [];
var letterIdx = [];
var centers = []; var centers = [];
@ -12,29 +12,17 @@ var score = 0;
var intervalID = -1; var intervalID = -1;
function prepareLetterIdx () { function biSearch(w, ws, start, end, count) {
"compile" "compile"
var li = [0]; if (start>end-w.legnth || count--<=0) return ws.substr(start, end-start).indexOf("\n"+w+"\n");
if (S.read("bee_lindex.json")!==undefined) li = S.readJSON("bee_lindex.json"); // check for cached index var mid = (end+start)>>1;
else { if (ws[mid-1]==="\n") --mid;
for (var i=1; i<26; ++i) { else while (mid<end && ws[mid]!=="\n") mid++;
var prefix = String.fromCharCode(97+i%26); var i = 0;
console.log(prefix); while (i<w.length && ws[mid+i+1]==w[i]) ++i;
li.push(S.read('bee.words').indexOf("\n"+prefix, li[i-1])+1); 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);
li.push(S.read('bee.words').length); if (w[i]>ws[mid+i+1]) return biSearch(w, ws, mid+1, end, count);
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;
} }
function isPangram(w) { function isPangram(w) {
@ -46,7 +34,7 @@ function isPangram(w) {
function checkWord (w) { function checkWord (w) {
if (w.indexOf(String.fromCharCode(97+letters[0]))==-1) return false; // does it contain central letter? 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 (foundWords.indexOf(w)>=0) return false; // already found
if (findWord(w)) { if (biSearch(w, words, 0, words.length, 20)>-1) {
foundWords.push(w); foundWords.push(w);
foundWords.sort(); foundWords.sort();
if (w.length==4) score++; if (w.length==4) score++;
@ -93,13 +81,12 @@ function pickLetters() {
var ltrs = ""; var ltrs = "";
while (ltrs.length!==7) { while (ltrs.length!==7) {
ltrs = []; ltrs = [];
var j = Math.floor(26*Math.random()); var i = Math.floor((words.length-10)*Math.random());
var i = Math.floor((letterIdx[j].length-10)*Math.random()); while (words[i]!="\n" && i<words.length) ++i;
while (letterIdx[j][i]!="\n" && i<letterIdx[j].length) ++i; if (i<words.length-1) {
if (i<letterIdx[j].length-1) {
++i; ++i;
while (letterIdx[j][i]!=="\n") { while (words[i]!=="\n") {
var c = letterIdx[j][i]; var c = words[i];
if (ltrs.indexOf(c)===-1) ltrs += c; if (ltrs.indexOf(c)===-1) ltrs += c;
++i; ++i;
} }
@ -187,7 +174,6 @@ function showWordList() {
}); });
} }
prepareLetterIdx();
pickLetters(); pickLetters();
drawHive(); drawHive();
drawScore(); 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", "name": "Bee",
"shortName":"Bee", "shortName":"Bee",
"icon": "app.png", "icon": "app.png",
"version":"0.02", "version":"0.03",
"description": "Spelling bee", "description": "Spelling bee",
"supports" : ["BANGLEJS2"], "supports" : ["BANGLEJS2"],
"readme": "README.md", "readme": "README.md",
@ -10,7 +10,6 @@
"storage": [ "storage": [
{"name":"bee.app.js","url":"bee.app.js"}, {"name":"bee.app.js","url":"bee.app.js"},
{"name":"bee.words","url":"bee_words_2of12"}, {"name":"bee.words","url":"bee_words_2of12"},
{"name":"bee_lindex.json","url":"bee_lindex.json"},
{"name":"bee.img","url":"app-icon.js","evaluate":true} {"name":"bee.img","url":"app-icon.js","evaluate":true}
] ]
} }