Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
232 lines (230 sloc) 6.88 KB
words = (text) -> (t for t in text.toLowerCase().split(/[^a-z]+/) when t.length > 0)
Array::or = (arrayFunc) -> if @length > 0 then @ else arrayFunc()
Array::flat = -> if @length == 0 then @ else @[0].concat(@[1..].flat())
train = (features) ->
model = {}
(model[f] = if model[f] then model[f] +1 else 2) for f in features
return model
NWORDS = train(words(require('fs').readFileSync('./lib/big.txt', 'utf8')))
alphabet = 'abcdefghijklmnopqrstuvwxyz'.split ""
edits1 = (word) ->
s = ([word.substring(0, i), word.substring(i)] for i in [0..word.length])
deletes = (a.concat b[1..] for [a, b] in s when b.length > 0)
transposes = (a + b[1] + b[0] + b.substring(2) for [a, b] in s when b.length > 1)
replaces = (a + c + b.substring(1) for c in alphabet for [a, b] in s when b.length > 0)
inserts = (a + c + b for c in alphabet for [a, b] in s)
return deletes.concat transposes.concat replaces.flat().concat inserts.flat()
known_edits2 = (word) -> ((e2 for e2 in edits1(e1) when NWORDS[e2]? for e1 in edits1(word)).flat())
known = (words) -> (w for w in words when NWORDS[w])
correct = (word) ->
candidates = known([word]).or -> known(edits1(word)).or -> known_edits2(word).or -> [word]
({k: w, v: NWORDS[w] or 1} for w in candidates).sort((a, b)-> b.v - a.v)[0].k
# Full test.
inOut =
'usefull': 'useful'
'concider': 'consider'
'triangulaur': 'triangular'
'hierchy': 'hierarchy'
'occurence': 'occurrence'
'occurence': 'occurrence'
'valubale': 'valuable'
'valuble': 'valuable'
'unexpcted': 'unexpected'
'unexpeted': 'unexpected'
'unexspected': 'unexpected'
'comittee': 'committee'
'scisors': 'scissors'
'sissors': 'scissors'
'managment': 'management'
'singulaur': 'singular'
'extreamly': 'extremely'
'intial': 'initial'
'cemetary': 'cemetery'
'supercede': 'supersede'
'reafreshment': 'refreshment'
'refreshmant': 'refreshment'
'refresment': 'refreshment'
'refressmunt': 'refreshment'
'galery': 'gallery'
'gallary': 'gallery'
'gallerry': 'gallery'
'gallrey': 'gallery'
'pronounciation': 'pronunciation'
'inconvienient': 'inconvenient'
'inconvient': 'inconvenient'
'inconvinient': 'inconvenient'
'cuaritains': 'curtains'
'curtans': 'curtains'
'curtians': 'curtains'
'somone': 'someone'
'familes': 'families'
'febuary': 'february'
'extented': 'extended'
'ofen': 'often'
'offen': 'often'
'offten': 'often'
'ofton': 'often'
'undersand': 'understand'
'undistand': 'understand'
'basicaly': 'basically'
'descide': 'decide'
'particulaur': 'particular'
'afful': 'awful'
'neccesary': 'necessary'
'necesary': 'necessary'
'neccesary': 'necessary'
'necassary': 'necessary'
'necassery': 'necessary'
'neccasary': 'necessary'
'uneque': 'unique'
'conciderable': 'considerable'
'remeber': 'remember'
'rememmer': 'remember'
'rermember': 'remember'
'articals': 'articles'
'aranged': 'arranged'
'arrainged': 'arranged'
'unfortunatly': 'unfortunately'
'varable': 'variable'
'wether': 'whether'
'leval': 'level'
'transfred': 'transferred'
'astablishing': 'establishing'
'establising': 'establishing'
'recieve': 'receive'
'benifit': 'benefit'
'remine': 'remind'
'fisited': 'visited'
'viseted': 'visited'
'vistied': 'visited'
'problam': 'problem'
'proble': 'problem'
'promblem': 'problem'
'biscits': 'biscuits'
'biscuts': 'biscuits'
'bisquits': 'biscuits'
'buiscits': 'biscuits'
'buiscuts': 'biscuits'
'wote': 'wrote'
'pertend': 'pretend'
'protend': 'pretend'
'prtend': 'pretend'
'pritend': 'pretend'
'bicycal': 'bicycle'
'bycicle': 'bicycle'
'bycycle': 'bicycle'
'lagh': 'laugh'
'lugh': 'laugh'
'cirtain': 'certain'
'recipt': 'receipt'
'magnificnet': 'magnificent'
'magificent': 'magnificent'
'magnifcent': 'magnificent'
'magnifecent': 'magnificent'
'magnifiscant': 'magnificent'
'magnifisent': 'magnificent'
'magnificant': 'magnificent'
'litriture': 'literature'
'chalenges': 'challenges'
'chalenges': 'challenges'
'exstacy': 'ecstasy'
'ecstacy': 'ecstasy'
'descided': 'decided'
'stomac': 'stomach'
'stomache': 'stomach'
'stumache': 'stomach'
'questionaire': 'questionnaire'
'speaical': 'special'
'specail': 'special'
'specal': 'special'
'speical': 'special'
'realy': 'really'
'relley': 'really'
'relly': 'really'
'diffrent': 'different'
'clearical': 'clerical'
'monitering': 'monitoring'
'biult': 'built'
'possition': 'position'
'perhapse': 'perhaps'
'personnell': 'personnel'
'seperate': 'separate'
'poertry': 'poetry'
'poetre': 'poetry'
'poety': 'poetry'
'powetry': 'poetry'
'arragment': 'arrangement'
'acess': 'access'
'vairious': 'various'
'beetween': 'between'
'avaible': 'available'
'independant': 'independent'
'independant': 'independent'
'discription': 'description'
'opisite': 'opposite'
'oppasite': 'opposite'
'oppesite': 'opposite'
'oppisit': 'opposite'
'oppisite': 'opposite'
'opposit': 'opposite'
'oppossite': 'opposite'
'oppossitte': 'opposite'
'vairiant': 'variant'
'poims': 'poems'
'southen': 'southern'
'possable': 'possible'
'dirven': 'driven'
'vistors': 'visitors'
'completly': 'completely'
'levals': 'levels'
'experances': 'experiences'
'wantid': 'wanted'
'begining': 'beginning'
'accomodation': 'accommodation'
'acommodation': 'accommodation'
'acomodation': 'accommodation'
'volantry': 'voluntary'
'chaper': 'chapter'
'chaphter': 'chapter'
'chaptur': 'chapter'
'defenition': 'definition'
'scarcly': 'scarcely'
'scarecly': 'scarcely'
'scarely': 'scarcely'
'scarsely': 'scarcely'
'voteing': 'voting'
'benifits': 'benefits'
'carrer': 'career'
'spledid': 'splendid'
'splended': 'splendid'
'splended': 'splendid'
'contenpted': 'contented'
'contentid': 'contented'
'experance': 'experience'
'experiance': 'experience'
'poarple': 'purple'
'liaision': 'liaison'
'liason': 'liaison'
'definately': 'definitely'
'difinately': 'definitely'
'anut': 'aunt'
'arnt': 'aunt'
'defenitions': 'definitions'
'paralel': 'parallel'
'paralell': 'parallel'
'parrallel': 'parallel'
'parralell': 'parallel'
'parrallell': 'parallel'
'latets': 'latest'
'latiest': 'latest'
'latist': 'latest'
'inetials': 'initials'
'inistals': 'initials'
'initails': 'initials'
'initals': 'initials'
'intials': 'initials'
eq = (x, y) -> `x == y`
for input, expected of inOut
result = correct(input)
feedback = if eq(result, expected) then "ok" else "FAIL! (should be #{expected})"
console.log "#{input} -> #{result} #{feedback}"