diff --git a/apps/bee/ChangeLog b/apps/bee/ChangeLog index df0907283..cfb44c8e9 100644 --- a/apps/bee/ChangeLog +++ b/apps/bee/ChangeLog @@ -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 diff --git a/apps/bee/README.md b/apps/bee/README.md index c6461fb8e..3d0a4c14a 100644 --- a/apps/bee/README.md +++ b/apps/bee/README.md @@ -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) diff --git a/apps/bee/bee.app.js b/apps/bee/bee.app.js index ef1582baa..878e9763c 100644 --- a/apps/bee/bee.app.js +++ b/apps/bee/bee.app.js @@ -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 (midws[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