Performance in Python

Simple performance in Python can be measured by the profile module using a command like,

$ python3 -m profile <script.py> {{args to script.py}}

Measuring performance of a simple iteration of Tamil spell checker shows,

python3 -m profile demo.py 
u'இன்பம்',
u'ஆப்பம்',
u'இன்னம்',
u'இன்பன்',
u'அற்பம்',
u'அப்பம்',
u'அற்றம்',
u'அற்கம்',
u'அக்கம்',
u'அட்டம்',
u'அம்மம்',
u'அற்பர்',
u'அப்பன்',
u'அப்பர்',
u'அப்பல்',
u'அம்பர்',
u'அம்பல்',
u'அன்னம்',
u'அன்னன்',
u'அன்னல்',
u'அன்பன்',
L = 21
         3192524 function calls (2736876 primitive calls) in 32.678 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       39    0.002    0.000    0.022    0.001 :0(__build_class__)
        2    0.000    0.000    0.000    0.000 :0(__contains__)
     17/4    0.000    0.000    0.144    0.036 :0(__import__)
        2    0.000    0.000    0.000    0.000 :0(__new__)
       35    0.000    0.000    0.000    0.000 :0(_fix_co_filename)
        1    0.000    0.000    0.000    0.000 :0(_getframe)
      253    0.001    0.000    0.001    0.000 :0(acquire_lock)
        1    0.000    0.000    0.000    0.000 :0(add)
       94    0.000    0.000    0.000    0.000 :0(allocate_lock)
       44    0.001    0.000    0.002    0.000 :0(any)
   519988    2.090    0.000    2.090    0.000 :0(append)
       11    0.000    0.000    0.000    0.000 :0(bit_length)
        1    0.000    0.000    0.000    0.000 :0(callable)
        4    0.000    0.000    0.000    0.000 :0(cast)
   197036    0.815    0.000    0.815    0.000 :0(chr)
        1    0.000    0.000    0.000    0.000 :0(close)
        1    0.000    0.000    0.000    0.000 :0(cmp_to_key)
        3    0.000    0.000    0.000    0.000 :0(compile)
        1    0.000    0.000    0.000    0.000 :0(create_builtin)
        8    0.005    0.001    0.005    0.001 :0(create_dynamic)
        1    0.000    0.000    0.000    0.000 :0(dir)
       51    0.000    0.000    0.000    0.000 :0(endswith)
     37/1    0.001    0.000   32.675   32.675 :0(exec)
        1    0.000    0.000    0.000    0.000 :0(exec_builtin)
        8    0.000    0.000    0.000    0.000 :0(exec_dynamic)
        1    0.000    0.000    0.000    0.000 :0(exp)
       32    0.000    0.000    0.001    0.000 :0(extend)
       32    0.000    0.000    0.000    0.000 :0(find)
       17    0.000    0.000    0.000    0.000 :0(format)
       70    0.000    0.000    0.000    0.000 :0(from_bytes)
      117    0.001    0.000    0.001    0.000 :0(fspath)
   412207    1.985    0.000    1.985    0.000 :0(get)
      146    0.001    0.000    0.001    0.000 :0(get_ident)
      274    0.001    0.000    0.001    0.000 :0(getattr)
       36    0.001    0.000    0.001    0.000 :0(getcwd)
      168    0.001    0.000    0.001    0.000 :0(getlower)
       14    0.000    0.000    0.000    0.000 :0(globals)
      270    0.001    0.000    0.001    0.000 :0(hasattr)
        1    0.000    0.000    0.000    0.000 :0(index)
       20    0.000    0.000    0.000    0.000 :0(is_builtin)
       44    0.000    0.000    0.000    0.000 :0(is_frozen)
        6    0.000    0.000    0.000    0.000 :0(isidentifier)
      296    0.001    0.000    0.001    0.000 :0(isinstance)
        8    0.000    0.000    0.000    0.000 :0(items)
    64438    0.311    0.000    0.311    0.000 :0(join)
   172718    0.760    0.000    0.760    0.000 :0(keys)
129971/129966    0.664    0.000    0.664    0.000 :0(len)
        5    0.001    0.000    0.001    0.000 :0(listdir)
       35    0.010    0.000    0.010    0.000 :0(loads)
        2    0.000    0.000    0.000    0.000 :0(log)
        1    0.000    0.000    0.000    0.000 :0(lookup)
      101    0.000    0.000    0.000    0.000 :0(lower)
      102    0.000    0.000    0.000    0.000 :0(match)
        4    0.000    0.000    0.000    0.000 :0(max)
       39    0.000    0.000    0.000    0.000 :0(min)
        1    0.000    0.000    0.000    0.000 :0(open)
        1    0.000    0.000    0.000    0.000 :0(openssl_md5)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha1)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha224)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha256)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha384)
        1    0.000    0.000    0.000    0.000 :0(openssl_sha512)
    99429    0.397    0.000    0.397    0.000 :0(ord)
   172717    0.753    0.000    0.753    0.000 :0(pop)
       22    0.001    0.000    0.001    0.000 :0(print)
       37    0.002    0.000    0.002    0.000 :0(read)
      253    0.001    0.000    0.001    0.000 :0(release_lock)
        1    0.000    0.000    0.000    0.000 :0(replace)
        1    0.000    0.000    0.000    0.000 :0(repr)
        1    0.000    0.000    0.000    0.000 :0(rfind)
      354    0.002    0.000    0.002    0.000 :0(rpartition)
      977    0.004    0.000    0.004    0.000 :0(rstrip)
        1    0.000    0.000    0.000    0.000 :0(seed)
       25    0.000    0.000    0.000    0.000 :0(setattr)
        2    0.000    0.000    0.000    0.000 :0(setdefault)
        1    0.003    0.003    0.003    0.003 :0(setprofile)
        2    0.000    0.000    0.000    0.000 :0(sort)
   172718    1.104    0.000    1.104    0.000 :0(sorted)
        9    0.000    0.000    0.000    0.000 :0(split)
        1    0.013    0.013    0.013    0.013 :0(splitlines)
        1    0.000    0.000    0.000    0.000 :0(sqrt)
       14    0.000    0.000    0.000    0.000 :0(startswith)
      187    0.004    0.000    0.004    0.000 :0(stat)
    63896    0.314    0.000    0.314    0.000 :0(strip)
        4    0.000    0.000    0.000    0.000 :0(tolist)
        5    0.000    0.000    0.000    0.000 :0(translate)
        1    0.000    0.000    0.000    0.000 :0(union)
        4    0.000    0.000    0.000    0.000 :0(update)
        1    0.006    0.006    0.006    0.006 :0(utf_8_decode)
       73    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:103(release)
       48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:143(__init__)
       48    0.001    0.000    0.004    0.000 <frozen importlib._bootstrap>:147(__enter__)
       48    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap>:151(__exit__)
       73    0.001    0.000    0.003    0.000 <frozen importlib._bootstrap>:157(_get_module_lock)
       47    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:176(cb)
       25    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap>:194(_lock_unlock_module)
     70/4    0.001    0.000    0.149    0.037 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
      488    0.002    0.000    0.002    0.000 <frozen importlib._bootstrap>:222(_verbose_message)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:232(_requires_builtin_wrapper)
       44    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:307(__init__)
       44    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:311(__enter__)
       44    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap>:318(__exit__)
      176    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:321(<genexpr>)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:35(_new_module)
       45    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:369(__init__)
       78    0.001    0.000    0.006    0.000 <frozen importlib._bootstrap>:403(cached)
       72    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap>:416(parent)
       44    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:424(has_location)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:433(spec_from_loader)
       44    0.002    0.000    0.010    0.000 <frozen importlib._bootstrap>:504(_init_module_attrs)
       44    0.001    0.000    0.018    0.000 <frozen importlib._bootstrap>:564(module_from_spec)
       47    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:58(__init__)
     44/4    0.002    0.000    0.151    0.038 <frozen importlib._bootstrap>:651(_load_unlocked)
       45    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:707(find_spec)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:728(create_module)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:736(exec_module)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:753(is_package)
       73    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:78(acquire)
       44    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap>:780(find_spec)
      133    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:843(__enter__)
      133    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap>:847(__exit__)
       45    0.002    0.000    0.044    0.001 <frozen importlib._bootstrap>:870(_find_spec)
     48/3    0.001    0.000    0.156    0.052 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
     48/3    0.002    0.000    0.156    0.052 <frozen importlib._bootstrap>:966(_find_and_load)
    72/24    0.001    0.000    0.139    0.006 <frozen importlib._bootstrap>:997(_handle_fromlist)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1067(_path_hooks)
      106    0.001    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:1080(_path_importer_cache)
       44    0.002    0.000    0.037    0.001 <frozen importlib._bootstrap_external>:1117(_get_spec)
       44    0.000    0.000    0.038    0.001 <frozen importlib._bootstrap_external>:1149(find_spec)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1196(__init__)
       40    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1202(<genexpr>)
       43    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:1228(_get_spec)
       89    0.007    0.000    0.031    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)
        5    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:1281(_fill_cache)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1310(<setcomp>)
        5    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:1322(path_hook_for_FileFinder)
       70    0.003    0.000    0.009    0.000 <frozen importlib._bootstrap_external>:263(cache_from_source)
       43    0.001    0.000    0.006    0.000 <frozen importlib._bootstrap_external>:361(_get_cached)
       89    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:37(_relax_case)
       35    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:393(_check_name_wrapper)
       35    0.001    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:430(_validate_bytecode_header)
       35    0.001    0.000    0.011    0.000 <frozen importlib._bootstrap_external>:485(_compile_bytecode)
       70    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:52(_r_long)
       43    0.001    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:524(spec_from_file_location)
      453    0.005    0.000    0.016    0.000 <frozen importlib._bootstrap_external>:57(_path_join)
      453    0.006    0.000    0.009    0.000 <frozen importlib._bootstrap_external>:59(<listcomp>)
       70    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:63(_path_split)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:669(create_module)
     35/4    0.001    0.000    0.149    0.037 <frozen importlib._bootstrap_external>:672(exec_module)
       35    0.002    0.000    0.024    0.001 <frozen importlib._bootstrap_external>:743(get_code)
      187    0.001    0.000    0.005    0.000 <frozen importlib._bootstrap_external>:75(_path_stat)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:800(__init__)
       35    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:825(get_filename)
       35    0.002    0.000    0.003    0.000 <frozen importlib._bootstrap_external>:830(get_data)
       35    0.000    0.000    0.001    0.000 <frozen importlib._bootstrap_external>:840(path_stats)
       63    0.001    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:85(_path_is_mode_type)
        8    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:908(__init__)
        8    0.000    0.000    0.006    0.001 <frozen importlib._bootstrap_external>:919(create_module)
        8    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:927(exec_module)
       58    0.000    0.000    0.002    0.000 <frozen importlib._bootstrap_external>:94(_path_isfile)
        5    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:99(_path_isdir)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 <string>:5(DictionaryWithPredicate)
        1    0.000    0.000    0.000    0.000 TextSummaryExtractor.py:19(SummaryTool)
        1    0.000    0.000    0.000    0.000 TextSummaryExtractor.py:3(<module>)
        1    0.000    0.000    0.000    0.000 __future__.py:48(<module>)
        1    0.000    0.000    0.000    0.000 __future__.py:78(_Feature)
        9    0.000    0.000    0.000    0.000 __future__.py:79(__init__)
        1    0.000    0.000    0.000    0.000 __init__.py:1(<module>)
        1    0.000    0.000    0.004    0.004 __init__.py:3(<module>)
        1    0.000    0.000    0.002    0.002 __init__.py:357(namedtuple)
        2    0.000    0.000    0.023    0.012 __init__.py:4(<module>)
        2    0.000    0.000    0.000    0.000 __init__.py:420(<genexpr>)
        2    0.000    0.000    0.000    0.000 __init__.py:422(<genexpr>)
        1    0.000    0.000    0.120    0.120 __init__.py:6(<module>)
       43    0.000    0.000    0.000    0.000 _compat_pickle.py:165(<genexpr>)
       85    0.000    0.000    0.000    0.000 _compat_pickle.py:167(<genexpr>)
        1    0.000    0.000    0.001    0.001 _compat_pickle.py:9(<module>)
       14    0.000    0.000    0.000    0.000 abc.py:9(abstractmethod)
        1    0.000    0.000    0.003    0.003 bisect.py:1(<module>)
        1    0.000    0.000    0.000    0.000 codecs.py:347(__init__)
        1    0.000    0.000    0.000    0.000 codecs.py:422(__init__)
        1    0.000    0.000    0.007    0.007 codecs.py:450(read)
        1    0.000    0.000    0.020    0.020 codecs.py:603(readlines)
        1    0.000    0.000    0.000    0.000 codecs.py:678(__init__)
        1    0.000    0.000    0.020    0.020 codecs.py:704(readlines)
        1    0.000    0.000    0.000    0.000 codecs.py:744(__enter__)
        1    0.000    0.000    0.000    0.000 codecs.py:747(__exit__)
        1    0.000    0.000    0.000    0.000 codecs.py:862(open)
        5    0.000    0.000    0.000    0.000 copy.py:66(copy)
        1    0.000    0.000    0.000    0.000 datastore.py:115(Node)
   172718    1.404    0.000    1.404    0.000 datastore.py:116(__init__)
        1    0.000    0.000    0.000    0.000 datastore.py:122(DTrie)
        1    0.000    0.000    0.000    0.000 datastore.py:126(__init__)
        1    0.000    0.000    0.000    0.000 datastore.py:14(Queue)
      222    0.003    0.000    0.058    0.000 datastore.py:140(isWord)
      222    0.012    0.000    0.055    0.000 datastore.py:146(isWordAndTrie)
    63896    4.643    0.000   18.098    0.000 datastore.py:178(add)
        1    0.000    0.000    0.000    0.000 datastore.py:236(getAllWordsIterable)
518546/63897    8.297    0.000   11.944    0.000 datastore.py:239(getAllWordsIterableHelper)
        1    0.000    0.000    0.000    0.000 datastore.py:252(RTrie)
        1    0.000    0.000    0.000    0.000 datastore.py:285(TamilTrie)
        1    0.000    0.000    0.016    0.016 datastore.py:4(<module>)
        1    0.000    0.000    0.000    0.000 datastore.py:53(Trie)
        1    0.000    0.000    0.000    0.000 datastore.py:56(__init__)
    64097    0.641    0.000    8.865    0.000 datastore.py:60(get_letters_impl)
        1    0.000    0.000   32.675   32.675 demo.py:5(<module>)
        1    0.000    0.000    0.000    0.000 dictionary.py:111(Agarathi)
        1    0.000    0.000    0.000    0.000 dictionary.py:112(__init__)
    63896    0.657    0.000   18.755    0.000 dictionary.py:139(add)
      222    0.002    0.000    0.060    0.000 dictionary.py:145(isWord)
        1    0.000    0.000    0.000    0.000 dictionary.py:151(getDictionaryPath)
    63897    0.496    0.000   12.440    0.000 dictionary.py:157(getAllWordsIterable)
        1    0.000    0.000    0.000    0.000 dictionary.py:16(Dictionary)
        1    0.000    0.000    0.000    0.000 dictionary.py:170(EmptyAgarathi)
        1    0.000    0.000    0.000    0.000 dictionary.py:174(TamilVU)
        1    0.000    0.000    0.000    0.000 dictionary.py:175(__init__)
        1    0.000    0.000    0.000    0.000 dictionary.py:178(EnglishLinux)
        1    0.000    0.000    0.000    0.000 dictionary.py:189(VatamozhiMonierWilliams)
        1    0.000    0.000    0.000    0.000 dictionary.py:193(ParallelDictionary)
        1    0.000    0.000    0.000    0.000 dictionary.py:210(Madurai)
        1    0.000    0.000    0.000    0.000 dictionary.py:217(Wikipedia)
        1    0.000    0.000    0.000    0.000 dictionary.py:225(DictionaryBuilder)
        1    0.000    0.000   32.416   32.416 dictionary.py:226(create)
        1    0.000    0.000    0.023    0.023 dictionary.py:4(<module>)
        1    0.279    0.279   12.719   12.719 dictionary.py:47(getSize)
        1    0.608    0.608   19.697   19.697 dictionary.py:58(loadWordFile)
        1    0.000    0.000    0.000    0.000 dictionary.py:71(SimpleDictionary)
        1    0.000    0.000    0.014    0.014 encode2unicode.py:23(<module>)
        1    0.005    0.005    0.005    0.005 encode2utf8.py:24(<module>)
      166    0.001    0.000    0.003    0.000 enum.py:265(__call__)
      166    0.001    0.000    0.002    0.000 enum.py:515(__new__)
       33    0.000    0.000    0.000    0.000 enum.py:592(name)
        2    0.000    0.000    0.000    0.000 enum.py:597(value)
        2    0.000    0.000    0.001    0.001 enum.py:758(_missing_)
        2    0.000    0.000    0.001    0.001 enum.py:765(_create_pseudo_member_)
        9    0.000    0.000    0.002    0.000 enum.py:795(__or__)
       74    0.001    0.000    0.003    0.000 enum.py:801(__and__)
       11    0.000    0.000    0.000    0.000 enum.py:820(_high_bit)
        2    0.000    0.000    0.001    0.001 enum.py:837(_decompose)
        2    0.000    0.000    0.001    0.000 enum.py:855(<listcomp>)
        5    0.000    0.000    0.000    0.000 enum.py:866(<lambda>)
       15    0.000    0.000    0.000    0.000 enum.py:872(_power_of_two)
       14    0.000    0.000    0.005    0.000 hashlib.py:116(__get_openssl_constructor)
        1    0.000    0.000    0.010    0.010 hashlib.py:54(<module>)
        8    0.000    0.000    0.004    0.001 hashlib.py:73(__get_builtin_constructor)
        1    0.000    0.000    0.000    0.000 ipaconvert.py:24(<module>)
        1    0.000    0.000    0.003    0.003 numeral.py:5(<module>)
        1    0.000    0.000    0.000    0.000 orddic.py:5(<module>)
        1    0.000    0.000    0.005    0.005 pickle.py:181(<listcomp>)
        1    0.000    0.000    0.000    0.000 pickle.py:184(_Framer)
        1    0.000    0.000    0.000    0.000 pickle.py:220(_Unframer)
        1    0.000    0.000    0.013    0.013 pickle.py:24(<module>)
        1    0.000    0.000    0.000    0.000 pickle.py:345(_Pickler)
        1    0.000    0.000    0.000    0.000 pickle.py:64(PickleError)
        1    0.000    0.000    0.000    0.000 pickle.py:68(PicklingError)
        1    0.000    0.000    0.000    0.000 pickle.py:75(UnpicklingError)
        1    0.000    0.000    0.000    0.000 pickle.py:88(_Stop)
        1    0.000    0.000    0.000    0.000 pickle.py:986(_Unpickler)
        1    0.000    0.000    0.000    0.000 posixpath.py:102(split)
        1    0.000    0.000    0.000    0.000 posixpath.py:329(normpath)
        1    0.000    0.000    0.000    0.000 posixpath.py:367(abspath)
        2    0.000    0.000    0.000    0.000 posixpath.py:39(_get_sep)
        1    0.000    0.000    0.000    0.000 posixpath.py:62(isabs)
        1    0.000    0.000    0.000    0.000 pprint.py:35(<module>)
        1    0.000    0.000    0.000    0.000 pprint.py:72(_safe_key)
        1    0.000    0.000    0.000    0.000 pprint.py:98(PrettyPrinter)
        1    0.000    0.000   32.678   32.678 profile:0(<code object <module> at 0x102c77810, file "demo.py", line 5>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.000    0.000 qwertykbd.py:9(<module>)
        1    0.000    0.000    0.021    0.021 random.py:38(<module>)
        1    0.000    0.000    0.000    0.000 random.py:663(SystemRandom)
        1    0.000    0.000    0.000    0.000 random.py:71(Random)
        1    0.000    0.000    0.000    0.000 random.py:87(__init__)
        1    0.000    0.000    0.000    0.000 random.py:96(seed)
      102    0.001    0.000    0.004    0.000 re.py:169(match)
        2    0.000    0.000    0.020    0.010 re.py:231(compile)
        1    0.000    0.000    0.000    0.000 re.py:249(escape)
      104    0.001    0.000    0.022    0.000 re.py:286(_compile)
        1    0.000    0.000    0.000    0.000 regexp.py:5(<module>)
        1    0.000    0.000    0.000    0.000 resources.py:10(<listcomp>)
        1    0.000    0.000    0.000    0.000 resources.py:13(get_data_dir)
        1    0.000    0.000    0.000    0.000 resources.py:17(get_data_dictionaries)
        1    0.000    0.000    0.000    0.000 resources.py:28(get_data_categories)
       14    0.000    0.000    0.000    0.000 resources.py:42(mk_path)
        1    0.000    0.000    0.001    0.001 resources.py:5(<module>)
        1    0.000    0.000    0.000    0.000 resources.py:9(_make_dict_with_path)
        1    0.000    0.000    0.000    0.000 santhirules.py:4(<module>)
      164    0.001    0.000    0.002    0.000 sre_compile.py:102(fixup)
        8    0.000    0.000    0.005    0.001 sre_compile.py:223(_compile_charset)
        8    0.002    0.000    0.005    0.001 sre_compile.py:250(_optimize_charset)
        5    0.000    0.000    0.000    0.000 sre_compile.py:376(_mk_bitmap)
        5    0.000    0.000    0.000    0.000 sre_compile.py:378(<listcomp>)
        4    0.000    0.000    0.000    0.000 sre_compile.py:381(_bytes_to_codes)
        4    0.000    0.000    0.000    0.000 sre_compile.py:388(_simple)
        2    0.000    0.000    0.000    0.000 sre_compile.py:414(_get_literal_prefix)
        2    0.000    0.000    0.000    0.000 sre_compile.py:441(_get_charset_prefix)
        3    0.000    0.000    0.001    0.000 sre_compile.py:482(_compile_info)
        6    0.000    0.000    0.000    0.000 sre_compile.py:539(isstring)
        3    0.000    0.000    0.012    0.004 sre_compile.py:542(_code)
        3    0.000    0.000    0.022    0.007 sre_compile.py:557(compile)
     16/3    0.001    0.000    0.011    0.004 sre_compile.py:64(_compile)
       16    0.000    0.000    0.000    0.000 sre_parse.py:111(__init__)
       15    0.000    0.000    0.000    0.000 sre_parse.py:159(__len__)
       48    0.000    0.000    0.001    0.000 sre_parse.py:163(__getitem__)
        4    0.000    0.000    0.000    0.000 sre_parse.py:167(__setitem__)
       18    0.000    0.000    0.000    0.000 sre_parse.py:171(append)
    24/11    0.000    0.000    0.001    0.000 sre_parse.py:173(getwidth)
        3    0.000    0.000    0.000    0.000 sre_parse.py:223(__init__)
      329    0.001    0.000    0.001    0.000 sre_parse.py:232(__next)
       51    0.000    0.000    0.000    0.000 sre_parse.py:248(match)
      270    0.002    0.000    0.003    0.000 sre_parse.py:253(get)
        4    0.000    0.000    0.000    0.000 sre_parse.py:266(getuntil)
       24    0.000    0.000    0.000    0.000 sre_parse.py:285(tell)
        1    0.000    0.000    0.000    0.000 sre_parse.py:287(seek)
        3    0.000    0.000    0.000    0.000 sre_parse.py:342(_escape)
      8/3    0.000    0.000    0.009    0.003 sre_parse.py:407(_parse_sub)
     11/3    0.002    0.000    0.009    0.003 sre_parse.py:470(_parse)
        3    0.000    0.000    0.000    0.000 sre_parse.py:76(__init__)
       14    0.000    0.000    0.000    0.000 sre_parse.py:81(groups)
        3    0.000    0.000    0.001    0.000 sre_parse.py:828(fix_flags)
        4    0.000    0.000    0.000    0.000 sre_parse.py:84(opengroup)
        3    0.000    0.000    0.010    0.003 sre_parse.py:844(parse)
        4    0.000    0.000    0.000    0.000 sre_parse.py:96(closegroup)
        1    0.000    0.000    0.021    0.021 string.py:15(<module>)
        1    0.000    0.000    0.000    0.000 string.py:169(Formatter)
        1    0.000    0.000    0.000    0.000 string.py:55(_TemplateMetaclass)
        1    0.000    0.000    0.020    0.020 string.py:65(__init__)
        1    0.000    0.000    0.000    0.000 string.py:77(Template)
        1    0.001    0.001    0.002    0.002 tace16.py:358(<listcomp>)
        1    0.000    0.000    0.002    0.002 tace16.py:4(<module>)
        1    0.000    0.000    0.000    0.000 tamil99kbd.py:11(<module>)
        1    0.000    0.000    0.000    0.000 transliteration.py:23(<module>)
        1    0.001    0.001    0.002    0.002 tscii.py:13(<module>)
      256    0.001    0.000    0.001    0.000 tscii.py:16(<lambda>)
        1    0.000    0.000    0.000    0.000 tweetparser.py:12(TweetParser)
        1    0.000    0.000    0.000    0.000 tweetparser.py:60(TamilTweetParser)
        1    0.000    0.000    0.004    0.004 tweetparser.py:9(<module>)
       35    0.000    0.000    0.000    0.000 types.py:135(__get__)
        1    0.000    0.000    0.147    0.147 typographical.py:14(<module>)
    632/1    0.026    0.000    0.041    0.041 typographical.py:20(oridam_generate_patterns)
        1    0.001    0.001    0.102    0.102 typographical.py:50(corrections)
        1    0.000    0.000    0.000    0.000 unicode2encode.py:25(<module>)
        1    0.000    0.000    0.003    0.003 unicode2ipa.py:23(<module>)
        1    0.003    0.003    0.031    0.031 utf8.py:11(<module>)
        1    0.000    0.000    0.000    0.000 utf8.py:159(<listcomp>)
      288    0.001    0.000    0.001    0.000 utf8.py:234(uyir_len)
      288    0.001    0.000    0.001    0.000 utf8.py:237(mei_len)
      288    0.003    0.000    0.005    0.000 utf8.py:274(uyirmei_constructed)
    98518    1.125    0.000    1.940    0.000 utf8.py:303(<lambda>)
        4    0.000    0.000    0.000    0.000 utf8.py:384(_make_set)
    64097    4.222    0.000    8.224    0.000 utf8.py:393(get_letters)
        1    0.000    0.000    0.000    0.000 utf8.py:758(CacheGetLettersMixin)
        1    0.000    0.000    0.000    0.000 utf8.py:760(__init__)
    64118    0.895    0.000   10.059    0.000 utf8.py:767(get_letters)
        1    0.000    0.000    0.000    0.000 wordutils.py:310(DictionaryFixedWordList)
        1    0.000    0.000    0.029    0.029 wordutils.py:4(<module>)

Basically, this confirms solthiruthi, and similar search based spellers, as a computational problem for Tamil spell checkers claimed in our paper. Performance is all it takes to make the results better, more accurate and faster.

சொல்திருத்தி – தெறிந்தவை 6

மொழியில் ஆக்க சக்திகளை தோராயமாக, தொல்கப்பியம், இலக்கணம் எல்லாம் தெறியாமலேயே ஒரு மொழியின் மாதிரியில் இருந்து (புள்ளியியல் வழி உருவாக்கியது) சரியான அல்லது பிழையான சொல், வாக்கியம், சொல் அமையும் இடம், இடம்-பொருள் ஒற்றுமை போன்றவற்றை நாம் சரியாக சொல்லலாம். அதற்கு மொழிமாதிரி கேட்குது நம்ம கணினி.

பொது தமிழ் தரவுகள் ஆகியவை

  1. மதுரை திட்டம்
  2. தமிழ் விக்கிப்பீடியா
  3. freetamilebooks மின் புத்தக தரவு
  4. பிரபல நாளிதள், வார இதள், வலை இதள் போன்றவற்றின் தரவு.

இவை ஓவ்வொன்றும் ஒவ்வொரு கால கட்ட தமிழை, அல்லது பல கால கட்ட தமிழ் வழக்கை கொண்டவையாக அமைகின்றன. மென்மேலும், ஒவ்வொன்றும் வெவ்வேறு ‘header information’ மேலான்மை தகவல்களினுள் பொருத்தப்பட்டருக்கின்றன.

இதனை நாம் சரியாக புரிந்து கொண்டதன் பின்னரே ஒரு மொழி மாதிரியை உருவாக்கலாம். மொழி மாதிரி என்பது நிறுத்த சொற்கள் நீக்கப்பட்ட சொல் தரவினில் இருந்து மட்டுமே உருவாக்கியதாகவும், முழுக்க முழுக்க தேவையற்ற மேலான்மை தகவல்கள் இல்லாமல் இருக்க வேண்டும். இவை இருந்தால் சிறப்பாக ஒரு மொழி மாதிரியை தயார் செய்யலாம்; இதனை எனது டுவீட்டில் பார்க்கலாம்:

ஏற்கனவே செய்த வேலைகளில் இந்த குறைபாடுகள் இருந்திருக்கின்றன; இப்போது தான் தெறிந்துகொண்டேன்.

சமீபத்தில் இந்த சிக்கலில் மாட்டினேன்: சரியான தொடக்க நிலையில் இருந்து தொடங்குவது அவசியம். நான் விக்கிபீடியா தரவை அப்படியே header-information உடன் எதையும் துப்புரவு செய்யாமல் 13 இலட்சம் சொற்களை வரிசைடுத்தினேன். எல்லாம் பிரயோஜனத்துக்கிலை.

தவராக வரிசைபடுத்திய மேலான்மை சொற்கள்.

நக்கீரண் வேலை பார்க்க முயன்றால் கொஞ்சமாவது பயபக்தி வேண்டாமா ?

சொல்திருத்தி – தெறிந்தவை 5

கட்டுரைத் தொடரில் இந்த பதிவில் மேலோட்டமான சொல்திருத்தியின் பிழைதிருத்தம் அல்கோரிதம் எப்படி கட்டமைக்கப்பட்டிருக்கு என்றும் பார்க்கலாம்.

படம்1: மெக்சிகோவில் புனித குவடலூப்பே கன்னியின் படம் மிக பிரசித்தி பெற்றதாக அவர்கள் நம்புகின்றனர். எனக்கு பூண்டி மாதா, வேளங்கன்னி மாதா நினைவு. இடம்: பெர்க்கிலி, கலிபொனியா #மக்சிக்கோ #சுவர்ஓவியம் #ourladyofguadalupe

1 பிழைதிருத்தி அல்கோரிதம்

உள்ளீடு : உரையின் சொற்கள் ஒவ்வொன்றாக. இடம்-பொருள் விளங்குவதற்கு [context] நாம் சொல் இடம் பெரும் வரியை சூழலுக்கு உள்ளீடாக கொடுக்கலாம்.

வெளியீடு: தவரான சொற்களின் பட்டியல், மற்றும் இவ்வாறு பிழையான் சொற்களின் வாயில் என்ன வேற்று சொல்லை மற்றாக இணைக்கலாம் என்ற பட்டியல்.

இப்படிப்பட்ட ஒரு அல்கோரிதத்தை செயல்ப்படுத்த நமக்கு ஒரு சொல்பட்டியல் தேவை; இதை நாம் அகராதி என்று வழக்கு மாரி சொல்வோம். அதாவது நமக்கு சொல் மற்றும் அதன் சரியான எழுத்து வடிவம் மற்றுமே தேவை – சொல்லின் பொருள் முதலில் தேவை இல்லை. ஆகையால் இந்த சொல் பட்டியல் மட்டுமே அகராதி என்று நம்மால் கருதப்படும்.

முதல் படியாக உரையில் உள்ள சொற்கள் நேரடியே பட்டியலில் காணப்பட்டால் இதனை நாம் சரியான சொல் என்றும் அவற்றை நீக்கி விடலாம். எ.கா. “அவன் வாத்து முட்டை விருப்பம் கொண்டவளை மட்டுமே சமைக்க தேர்ந்தெடுப்பதாக சீனாவில் அறிவித்திருந்தான்” என்ற 10 சொல் வாக்கியத்தில் ‘அவன்’, ‘வத்து’, ‘முட்டை’, ‘விருப்பம்’, என்ற சொற்கள் சரியாக சொல் பட்டியலில் இருக்கும். தற்போது – 6 சொற்கள் மீதம் உள்ளன.

அடுத்தபடியாக பெயர்சொற்கள் அவற்றின் பட்டியல் கொண்டால் இதனையும் நாம் நீக்கிவிடலாம். மேல் உள்ள செயற்கையான உதாரனத்தில் ‘சீனா’ என்ற பெயர் சொல் நேரடியாக இந்த பட்டியலில் காணப்படும். தற்போது – 5 சொற்கள் மீதம் உள்ளன.

அடுத்தபடியாக வினைச்சொற்கள், மற்றும் இலக்கண வகைபடுத்தப்பட்ட இடைச்சொற்கள், ஆகுபெயர்கள், ஆகியவற்றை சரியாக பகுத்தாய்ந்து விதிகளுடன் உணர்ந்தால் சில அடிச்சொற்கள் கொண்ட பட்டியலின் வழியே மட்டும் அவற்றின் ஆக்கல் தன்மையின் வாயிலாக பல சொற்களை நாம் பகுத்தரியும் வகையில் அனுகலாம். தமிழில், இலத்தின் போல, வினைஎச்சங்கள், வினைச்சொற்கள் அவை வாக்கியத்தில் இடம் பெரும் இடங்கள் கண்டு மருவி வருகிண்ரன. எ.கா. ‘அவன் ஒரு சட்டை வாங்க சென்றான்’, ‘அவள் ஒரு சட்டை வாங்க சொல்வாள்’ என்ற இரு வாக்கியங்களில் ‘செல்’ என்ற சொல் மருவி ஆணுக்கு ‘சென்றான்’ என்றும் பெண்ணுக்கு ‘செல்வாள்’ என்றும் வருகிரது. இது சற்று சிக்கலான ஒரு அல்கொரிதத்தின் கீற்றாகவே அமைகிரது; இதனை அதிகம் மொழியியலாகவும் சற்று கம்மியாக கணினியியலாகவும் கருதலாம்.

 தமிழில் உள்ள இலக்கண விதிகளை பேரா. ராஜம் அவர்கள் letsgrammar.org  என்ற தளத்தில் வினைச்சொற்கள் எப்படி மருவும் என்ற விதிகளை மென்பொருளில் நிருவி அழகாக விளக்கியுள்ளார். இவற்றை ஆங்கிலத்தில் ‘word declension rules’ என்று சொல்வார்கள்.

எண்கள், வடமொழி சொற்கள், நிருத்த சொற்கள், பன்மை சொற்கள், ஆங்கில சொற்கள் ஆகியவற்றையும்  நாம் கண்டறிந்து உரையினை இவற்றிலிருந்து நீக்கம் அல்லது பிழை திருத்தம் செய்யலாம். தட்டுப்பிழைகள், ஒருங்குரி பிழைகள் போன்றவற்றையும் இந்நிலையில்  நாம் நீக்கிவிடலாம்.

2 பிழை வகைகள்

மேல் சொன்னபடி சொல்திருத்திகள் அவைகளின் நான்கு படினிலைகளில் ஏதேனும் ஒரு சொல்லை [உரையில் உள்ள] அந்தந்த வகுப்பில் உள்ளதாகவும் கண்டு, அதே சொல் தவராக உருவெடுத்திருந்தால் அது தவரான சொல் என்றும், அதனை நாம் சரிசெய்து – மாற்றங்களை பரிந்துரைக்கலாம். இதையே ‘wrong word error’ என்று சொல்லாம்.

கடைசியில், இவ்வாரு நான்கு படிகளில் நீக்கம் செய்யப்படாத சொற்களை நாம் அகராதியில் இல்லாத சொற்கள் என்று மட்டுமே கருதலாம். அதாவது இவற்றை ‘non-word error’ என்று கண்டறிந்து சொல்லாம். இவற்றில் நாம் மாற்று சொற்களை தரமுடியாது.

concordance தரவுகள் இருப்பின் ‘அன்பே சிவம் என்பர் சைவ சித்தாந்திகள்‘, மற்றும் ‘அன்பே சவம் என்பர் சைவ சித்தாந்திகள்‘ என்ற இரு வாக்கியங்களுக்கும் மாற்றுகள் மேல் கண்ட சொல்திருத்தியினை மேம்படுத்தி செயல்படுத்த செய்யலாம்.

3. வழங்கல்

இந்த  நிலைகள் முழுதும் ஒரு மேலோட்டமான ஒவ்வொரு சொல்திருத்தியின் கட்டமைப்பிலும் இருப்பதாக நாம் உணரலாம். 

சொல்திருத்தி என்பது உரையினை உள்வாங்கிக்கொண்டு சரியான சொற்களை முழுதும் கண்டுகொள்ளாது. தவரான சொற்களை மட்டுமே மையமாக கொண்டு இயங்குகிரது. என்னடா வாழ்க்கையிது, கால்ஃபு போல் சொல்திருத்திகள், எல்லாமே சரியான ஆட்டத்தினால் நிற்னயிக்கப்படுவதில்லை – பிழையான சொல், பிழையான ஆட்டம் அதே வெற்றியை நிற்னயிக்கிரது. இதன் பணி:

  1. தவரான சொற்களை சுட்டிக்காட்ட வேண்டும்
  2. தவரான சொற்களுக்கு மாற்றங்களை காட்ட வேண்டும்
  3. தவரான் சொல்லுக்கு பயனர் மாற்று தரவிருந்தால் அதனை சொல் பட்டியலில் சேர்த்துக்கொள்ள வேண்டும்; அதனை உரையிலும் மாற்றவேண்டும்.

கடைசியில் அனைத்து உள்ளீடுகளையும் ஒருங்கிணைத்து சரியான உரையை சொல்திருத்தி வழங்கும். 

சொல்திருத்தி – தெறிந்தவை 4

இந்த தொடரின் பதிவில் எப்படி ஒரு தட்டச்சு பிழைகளை தீர்க்கலாம் என்று பார்க்கலாம். இவையும் ஏற்கனவே கூறிய குறைவான திருத்தம் தொலைவு என்ற அளப்பின் சார்பின் கீழ் அலசப்படும் ஒரு கேள்வி. சரி, அப்ப என்ன புதுசா ?

படம் 1: தமிழ் 99 – விசைப்பலகை [ஆப்பிள் iOS 10.13-இல் உள்ளபடி]

1 ஏன், எப்படி

விஷயத்துக்கு வாரோம். புதுசு என்ன ? அதாவது தட்டச்சு பிழைகள் என்பது தமிழில் ஒரு வழி மட்டும் வருகின்றன – விசைபலகை வழியாக (typographical errors originate from keyboard). இதன் காரணமாக, நாம் ‘பாம்பின்கால் பாம்பு அறியும்’ என்பது போல், இந்த சிக்கல் உறுவாகும் இடத்தின் விசைப்பலகையின் கட்டமைப்பின் வழியாக இதனைத் தீர்வு காண முடியும். இதனை ‘அருகிலேயே உள்ள விசைப் பிழை’ என்றும் [nearest neighbor key error] சொல்லாம்.

2 செயல்முரை அல்கோரிதம்

தற்சமயம் தமிழ் 99 என்ற விசைபலகையில் உள்ளீடு செய்வது என்ற கொள்வோம். இதில் உள்ளீட்டு பிழை என்பது ‘இ’ என்ற எழுத்தை இடும் சமயம், ‘அ’, ‘ஈ’, ‘உ’, ‘ஓ’,’ஔ’ என்று கைவிரல் தவரி சொடுக்கினால் ‘இன்பம்’ என்ற சொல் உள்ளீடு ‘அன்பம்’ அல்லது ‘உன்பம்’ என்றும் மாற்றமடைவதற்கு வாப்புண்டு.

சரி: இன்பம், தவறு: அன்பம், உன்பம்

இப்போது ஆவனத்தில் இப்படி ஒரு பிழை வந்தது ‘அன்பம்‘ அல்லது ‘உன்பம்’. இதனை நாம் சொல் உள்ளீட்டு பிழை என்ற இந்த செயல்முறை அல்கோரிதத்தின் வழி திருத்தலாம். இந்த தட்டச்சுபிழை எழுத்து பிழை வாய்ப்புகள் அனைத்தும் ஒரு மயக்க அணியில் (‘confusion matrix’ என்று சொல்லக்கூடிய) நிரலிக்கு குறிப்பிட்டிருக்கவேண்டும். இதனை படம் 2-இல் காட்டுகிறோன்.

படம் 2: தமிழ் 99 iOS ஆப்பிள் திரன்பேசியில் உள்ள விசைபலகை குழப்ப/மயக்க அணி

இதற்கு மேற்கண்ட அல்கோரிதத்தை இயக்கினால் 56 மாற்றங்களைத்தரும். இவற்றில் சரியான் சொற்களை மட்டும், குறைந்த திருத்த தொலைவில் இருப்பவற்றை மட்டும் நாம் ஏற்றுக் கொண்டால் அதில் ‘இன்பம்’ என்ற சரியான் சொல் இருக்கிரது! இதுவே தட்டச்சு பிழை சொல்திருத்தியின் இயக்கம். இதனைப் பற்றி பல அறிவியலாளர்களும் எழுதியுள்ளார்கள் என்பது புதிய செய்தி இல்லை என்பதையும் இங்கு பதிவு செய்வது கவணத்தில் கொள்ளவேண்டியவை.

  1. ஈன்பம்
  2. இன்பம்
  3. ஆன்பம்
  4. உன்பம்
  5. ஊன்பம்
  6. அன்பம்
  7. ஔன்பம்
  8. ஈற்பம்
  9. ஈப்பம்
  10. ஈக்பம்
  11. ஈட்பம்
  12. ஈம்பம்
  13. இற்பம்
  14. இப்பம்
  15. இக்பம்
  16. இட்பம்
  17. இம்பம்
  18. ஆற்பம்
  19. ஆப்பம்
  20. ஆக்பம்
  21. ஆட்பம்
  22. ஆம்பம்
  23. ஈன்னம்
  24. ஈன்மம்
  25. ஈன்றம்
  26. ஈன்லம்
  27. ஈன்கம்
  28. ஈன்ஙம்
  29. ஈன்டம்
  30. இன்னம்
  31. இன்மம்
  32. இன்றம்
  33. இன்லம்
  34. இன்கம்
  35. இன்ஙம்
  36. இன்டம்
  37. ஆன்னம்
  38. ஆன்மம்
  39. ஆன்றம்
  40. ஆன்லம்
  41. ஆன்கம்
  42. ஆன்ஙம்
  43. ஆன்டம்
  44. அன்னம்
  45. அன்மம்
  46. அன்றம்
  47. அன்லம்
  48. அன்கம்
  49. அன்ஙம்
  50. அன்டம்
  51. அன்ணம்
  52. அன்தம்
  53. அன்ரம்
  54. அன்ளம்
  55. அன்எம்
  56. அன்வம்

4 செயல்படுத்துதல், குறிப்புகள்

இந்த அல்கோரிதத்தின் நிரலாக்கம் இங்கு ஓப்பன் தமிழ் திரட்டில் சேர்க்கப்பட்டது. இதனை நீங்கள் முழுதேடலில் இடம் கொடுத்தால் 2398 விடைகள் கிடைக்கும் – அதாவது முழு 4-எழுத்து சொல்லின் 4-எழுத்து தொலைவில் உள்ள திருத்தங்கள் எல்லாவற்றையும் தேடுவதால் உண்டாகும் தகவல் வெள்ளப்பெருக்கு; சாதாரணமாக 1 அல்லது 2 எழுத்துப்பிழைகள் மட்டுமே உள்ளன என்பது அறிவியலாளர்கள் கணிப்பு. இதை நாம் செயல்படுத்தும் ‘tree pruning search‘ அல்கொரிதம் வகையினால் நாம் 56 மாற்றங்களுக்குள் மட்டுமே தேடல்களை நடத்தி இந்த தட்டச்சு கைவிரல் தவரான உள்ளீட்டிற்கு தீர்வு காணலாம்.

இதன் சிக்கல் அளவு [computational complexity] என்பது, ஒரு n-எழுத்து சொல் என்று கொண்டால், O(k1 x k2 x k3 … kn ) = O( kn ) என்று அதிக பட்சமாக இருக்கலாம் என்று [ஏதோ ஒரு k > 0 எண்ணால்] என்று நம்மால் காட்டமுடியும்.

சொல்திருத்தி – தெறிந்தவை 3

இந்த தொடரில் இதுவரை ஆய்வுகளைப்பற்றி மட்டுமே இதுவரை பார்த்தோம். இப்போது சில செயல்முரை அல்கொரிதங்களை பார்க்கலாம்.

1 மேலோட்டமான சில குறிப்புகள்

சொல்திருத்தியில் பிழையான சொல் ஒன்றை முதலில் கண்டரிந்தபின், அதற்கு எப்படி ஒரு மாற்றை [என்ற ஒரு தோராயமான சொற்பிழை நீக்கப்பட்ட பொருத்தத்தை எப்படி] உருவாக்குவது ? இதற்கு தேவை திருத்தத் தொலைவு d.

இயற்ப்பியலில், புள்ளியியலில் இவ்வாரான் கேள்வியை ஒரு optimization வடிவத்தில் மாற்றி இதனை தீர்வுகாணலாம். இதனைப்போல் சொல்திருத்தியில்,

மாற்றுச் சொல் = arg-min [ d[ச,த] ]   

இதன் பொருள் என்ன என்றால் கொடுக்கப்பட்ட தவரான் சொல் த என்பதற்கு நமது செயலி அதன் அகராதியில் உள்ள ஒவ்வொரு சொல்லில்லும் அதன் தொலைவை கண்டறிந்து அவற்றில் எந்தெந்த சொற்கள் மிகக் குறைவான தொலைவில் உள்ளனவோ அவற்றையே சரியான சொல் என்ற பட்டியலில் பரிந்துரைக்கும். இதற்கு உதாரணமாக கட்டுரையின் மூன்றாவது பகுதியில் நிரல் துண்டு பார்க்கலாம்.

2 தொலைவு

தொலைவு – இரு சொற்களுக்கும் உள்ள நெறுக்கத்தை நாம் சொல்திருத்தியில் கணக்கிட வேண்டிய தேவை இருக்கிரது. ஏனெனில், ஒரு தவரான் சொல் உரையில் உள்ளீடு செய்யப்பட்டிருந்த்தால் அதற்கு மாற்றை தானியங்கி வழியில் கண்டறிய [அதவது இதன் மாற்றுச்ச்சொல்] இதற்கு பொருத்தமாகவும், நேருக்கமாகவும் இருக்கும் என்பது கணினியாளர்களும், மொழியியலாளர்களும் ஒப்புக்கொண்ட ஒரு கோட்பாடு. இதனை செயல்படுத்த கணினியாளர்கள் கொண்ட ஒரு மதிப்பீடு தொலைவு. இதனை திருத்தத் தொலைவு என்று சொல்வார்கள் [edit-distance].

ஒரு சொல்லினை அதன் உருப்பு எழுத்துக்களை இடம் மாற்றியோ, எழுத்துக்கள் கூட்டியே, அல்லது எழுத்துக்கள் நீக்கியோ மற்றொரு சொல்லாக மாற்ற எத்தனை படிகள் உள்ளன என்று கணக்கிட்டு சொல்வதானது இத்தகைய திருத்தத் தொலைவு சார்பு. இதனை கண்டுபிடித்த பலருள் திரு லெவின்ஷ்டீன் அவரது பெயரை இணைத்து லெவின்ஷ்டீன் திருத்தத் தொலைவு என்று கூறுகின்றார்கள் அறிவியலாளர்கள்.

இதன் பொருள் என்ன ? இதன் அமைப்பு எப்படிபட்டது ? கணிதவியலில், தினசரி வாழ்வில் எப்படி தொலைவு நிர்னயிக்கப்படுகிரது என்து போல், ஒரே இடத்தில் உள்ள பொருளுக்கும் அதே பொருளுக்கும் தொலைவு எதுவும் இல்லை – 0. அதே மாதிரி ஒரே சொல்லிர்கும் அதே சொல்லின் நகலுக்கும் தொலைவு 0. பிரகு, உங்கள் வீட்டிற்கும் உங்கள் பக்கத்துவீட்டிற்கும் தொலைவு என்ன ? தொலைவு 1 அல்லது கூடுதலாகவே இருக்கவேண்டும் இல்லையா ? பக்கத்து வீட்டார்க்கும் உங்கள் வீட்டிற்கும் உள்ள தொலைவு, உங்கள் வீட்டிற்கும் அவர்களது வீட்டிற்கும் உள்ள தொலைவும் ஒரேபடியானதாக இருக்கும். d[a,b] = d[b,a] என்பது ‘commutativity‘ என்ற சார்பின் குணத்தை இந்த திருத்த தொலைவு சார்பும் கொண்டது. [அதையும் – ‘போத்திக்குனு படுத்துக்கலாம், படுத்துக்குனு போத்திக்கலாம்‘ என்று பல முதிய தமிழ் மைக்கில் ஜாக்சன்கள் சொல்லியதை நினைவு கொள்ளலாம்]. அதுவே பொது அறிதல். இதைப்பொல குணங்களைக்கொண்ட சார்புகளை கணிதவியலில் ‘metric‘ என்றும் சொல்வார்கள் – அதாவது அளக்கும் சார்பு.

3 சிரிய எடுத்துக்காட்டு

ஒப்பன் தமிழ் நிரல் தொகுப்பில் ஒரு சில் உத்திகள் உள்ளது அவற்றில் திருத்தத் தொலைவு சார்பும் ஒன்று. இதனைக் கொண்டு ஒரு சிரிய உதாரனத்தை பார்க்கலாம்.

அகராதியில் உதாரனத்திற்கு 5 சொற்கள் இருக்கு என்று மட்டும் கொள்ளல்லாம்.

அகராதி A என்பதில் [‘அவிழ்’,’அவல்’,’அவள்’,’தவில்’,’தவள்’] என்ற் சொற்கள் இருக்கு என்றும் உள்ளிட்டு சொற்கள் ‘ஏவள்’, ‘இவல்’ என்று கொடுக்கபட்டது என்றும் கொள்வோம். இதற்கு என்ன மாற்றுக்கள் ?

பகுதி ஒன்றின் படி இந்த புள்ளியியல் குரைந்த பட்ச தெடலை பைத்தான் மொழியில் இப்படி எழுதலாம்:

இதனை இயக்கினால் நாம் பார்கக்கூடிய வெளியீடு இப்படி; அதாவது நமது சிரிய சொல்திருத்தி அல்கொரிதம் ‘ஏவள்’ என்பதை ‘அவள்’ என்றும், ‘இவல்’ என்பதை ‘அவல்’ என்றும் மாற்றாக பரிந்துரைக்கிரது. மேலும் கவனித்து பார்த்தால் ‘ஏவள்’ என்பது ‘தவள்’ என்பதற்கும் நெருக்கமான தொலைவில் உள்ளது ‘distance’ என்ற தொலைவு பட்டியலில் தெறியும்.

ஒப்பன் தமிழ் நிரல் மற்றும் இயக்கிய வெளிப்பாடு இங்கு.

மேலும் மற்ற அல்கோரிதங்களைப் பற்றி அடுத்த பதிவுகளில் மேலோட்டமாக பாற்கலாம்.

சொல்திருத்தி – தெறிந்தவை 2

சென்ற பதிவில் ஒரு தொடக்கத்தை ஆரம்பம் செய்தோம்; இந்த பதிவில் அதே வேகத்தில் தொடர்வோம். இடைவெளியில் மூன்று முக்கியமான அறிவியல் ஆராய்ச்சிசிகளை பற்றி உங்கள் கவணத்தை ஈர்த்து செல்ல விடுங்கள்.

குருட்டுப்புலி ருட்டுப்புலி, ஓக்லாண்டு, கலிபோர்னியா. 2019. படம்: முத்து அண்ணாமலை.
Blind Tiger, Oakland, CA.
குருட்டுப்புலி, ஓக்லாண்டு, கலிபோர்னியா. 2019. படம்: முத்து அண்ணாமலை

1 முதல் ஆய்வுகளின் முடிவு

சொல்திருத்திகளின் சவால்கள் – ஒரு கணக்கெடுப்பும், மேலோட்டமான விளக்கமும் என்ற தலைப்பில் கேரன் குகிச் என்ற ஆரய்ச்சியாளர் Techniques for automatically correcting words in text 1992-இல் ACM சஞ்சிகையில் அற்புதமாக விளக்கம் அளித்துள்ளார். இது ஒரு கணக்கெடுப்பு என்பதால் 63 பக்கங்கள் கொண்டதாக உள்ளது. கண்டிப்பாக சொல்திருத்தியில் ஆராய்ச்சி செய்ய முனைபவரும், செயல்படுத்துபவரும் இதை வாசித்தல் வேண்டும்.

2 சொந்தங்கள் அவை கண்ட அறிவு

அடுத்து எனது வாசிப்பில் நான் அலசி சல்லடைபோட்டு மீன்பிடித்ததில் இணைய வலையில் சிக்கிய மீன் – தங்கமீன் – இந்த துருக்கி அறிவியலாளர் குழு எழுதிய 1994-இல் வெளிவந்த இந்த கட்டுரை – ஒட்டு மொழிகளினுள் உண்டான அம்சங்களில் ஒரு சொல்திருத்தியை உருவாக்குவது எப்படி – Kemal Oflazer , Cemaleddin Güzey, Spelling correction in agglutinative languages,  PDF என்பதை மைய்யமாகக்கொண்டு கணிமை கோட்பாடுகளில் செயல்முறைகளை சாட்சியப்படுதினார்கள். ஃபின்னிஷ், துருக்கி போன்ற மொழிகள் தமிழைப்போல் ஒட்டு மொழி என்ற சொல்லடல் இலக்கண வகைப்படுத்தப்பட்டவை. ஃபின்னிஷ்-தமிழ் தொடர்பு மிக பெரியது – ஐராவதம் அவர்களைக் கேளுங்கள், இல்லை சிந்து சமவெளியில் போய் பாருங்கள் [விளையாட்டாதான்]!

3 கண் கெட்டபின் சூரிய நமஸ்காரம்

மூன்றாவதாக நான் சொல்வது பொதுவில் ‘எங்க அப்பன் குதிருக்குள்ள இல்லை’ என்ற பொது இரகசியமாக உள்ள தனபால் – கீதா அண்ணா பல்கலை அறிவியலாளர்களின் 2003-இல் வெளிவந்த கட்டுரை. இதில் பலவிதிகளை நாம் நேரடியாகவும், மேம்பாடு செய்தும் செயல்படுத்தலாம். “Tamil spell checker,”  என்று T. Dhanabalan, R Parthasarathi… – Sixth Tamil Internet 2003

4 அடுத்த படியாக

இவை எல்லாம் ஒரே நாளில் யாரும் படிக்க சுலபமாக முடியாது. இருந்தாலும் இப்படிப்பட்ட சிக்காலான் மொழியியல் காட்டிற்குள் அடங் கிய பூதம்தான் ஒரு சொல் திருத்தி. புகைப்போட்டோ பொரிவைத்தோ இந்த ஒரு சித்தாந்த சொல் அன்னத்தை வழிமரித்து பொது பயன்னுக்கு அளிப்பது, நமக்கும், வருங்கால தமிழ் எழுத்தாளர்களுக்கும், வாசகர்களுக்கும் உண்மையிலேயே ஒரு அளப்பரிய செயல். அடுத்த பதிவில் இந்த ஆராய்ச்சிகளில் உள்ள சில செயல்முரைகளின் உருவங்களையும், கீற்றுகளையும், நடைமுரை விளக்கங்களையும் பார்க்கலாம்.

சொல்திருத்தி – தெறிந்தவை 1

நோக்கம்

தமிழில் சொல்திருத்தி என்பது ஒரு இதநாள்வரை முழுமையாக, பல்வேரு மக்களும் ஒப்புதலுக்கினங்க, மன நிரைவுடன் பயன்படுத்தும் நிலையில் இல்லை. முயற்சிகள் எடுக்காத காரணித்தினால் அல்ல, காரணம் சவால் பெரிதாக உள்ளதனால் என்பது என் புரிதல். இந்த பதிவில் இந்த சொல்திருத்தி தேவைக்கு என்ன முயற்சிகள் எடுக்கப் பட்டுள்ளன என்றும், ஒரு கணிமயின் அடிப்படையில் இதில் உள்ள சவால்களை, சிக்கல்களை முன்னெடுத்து வரசெய்ய முயல்கிறேன். தமிழின் கூற்று ‘கற்றது கைமண் அளவு!’

சிக்கல் அளவு

தமிழ் மொழி ஒரு ஒட்டு மொழி – agglutinative language; மேலும் பேசப்படாத மொழிகளைப்போல் இல்லாமல் நல்ல இருவடிவம் [diglossic – பேச்சு-எழுத்து] என்றும் இது வடிவங்களைக் கொண்டதால் இந்த சொல்திருத்தியின் சாத்தியம் அதிகமான சிக்கல் அளவில் [computational complexity] உள்ளதை நாம் யுகிக்க முடிகிரது.

ஒரு ஒட்டுமொழியில், அதுவும் எதுகை-மோனை என்ற வடிவம்சார்ந்த விதிகளுடன், புணர்ச்சி விதிகளுடன், ஒரே வேர் சொல் பல வடிவங்களில் தொற்றம் பெற்று, ஜீவித்து, சிறு சிறு துளிகள் சேர்ந்து மொழியில் ஒரு படைப்பாளி அவள் செய்யும் தாக்கம் சுனாமியாக அசுர உருவம் எடுக்க தமிழ்வெளி இடமளிக்கிரது. இதன் மேல், இலக்கணம், கலை, அறிவியல், உளவியல், ஆன்மீகம், பண்பாடு, தொன்மை, வரலாறு, தொழில்நூட்பம் பொன்ற களங்கள் மொழியில் தழைக்கின்றன. வாழக்கையை செம்மைப்படுத்தி மொழியினால் ஒரு சிறப்பான் இடத்திற்கு நம்மை அழைத்துச் செல்கின்றன். இந்த மொழியில் சொல்வளம் [‘combinatorial explosion of morphologically rich language’ என்று சொல்லக்கூடிய] மொழியின் சொல்வடிவத்தின் வளமையை கட்டமைப்பாக கொண்டதனால் வந்த சொல் பெருக்கௌ என்று பொருள்கொள்ளலாம்.

சலிப்பாகும்படி சொன்னால், பலமே பலவீனமாகும் இடம் இந்த சொல்வடிவத்தின் வளமை என்றானது தமிழை செம்மைப்படுத்தப்போய் தமிழில் உள்ள பிழைகளை திருத்தம் செய்ய முயலும் அர்த்நாரீஸ்வரர்களின் வேலையை முழுதுமே முரியடிக்கும் நோக்கில் அமைந்தாயிற்று. காரணம் இத்தகைய சொல்வளத்தை முழுதும் கணினி நிரல்களில் ஏற்றாவிட்டாலும் இதில் 90% கீழ் இருந்தாலும் அந்த சொல்திருத்தி நிரல் சரிவர சொற்களை சரி-பிழை என்று பாகுகாடு அறியச்செய்யாது. இது ஒரு புரியாத புதிராக இன்றும் விளங்குகிரது. எனக்குத் தெறிந்தளவு தமிழில் பிழைதிருத்திகள் 50% சரியான விடைகளையே அளிக்கின்றது என்பது.

தெறிந்தவை – ஆய்வுகள் – புதுமை செய்தவர்

  1. முதன்மையான தமிழின் சொல்திருத்தியை ஆராச்சியே 2003-இல் இருந்தும் இன்றுவரை – சுமார் 17 ஆண்டு ரஜ்ஜியத்தில் உள்ளது: “Tamil spell checker,” என்று T. Dhanabalan, R Parthasarathi… – Sixth Tamil Internet 2003-இல் அண்ணா பல்களைக்கழகத்தில் இருந்து இவர்கள் உருவக்கினார்கள்.
  2. சில மயங்கொலி எழுத்துக்களை திருத்தம் செய்யும் வகை “A generic spell checker engine for south asian languages “, ABA Abdullah, A Rahman – … on Software Engineering and Applications (SEA …, – icita.org இவர்கள் 2003-இல் வெளிவந்தனர்.
  3. “சிங்கள மொழியில் சொல்திருத்தி – 2010-இல் A WasalaR Weerasinghe…இவர்கள் இங்கும் “A data-driven approach to checking and correcting spelling errors in sinhala” – Int. J. Adv. ICT …, 2010
  4. சிந்தி மொழியில் சொல்திருத்தி – 2015-இல் Z Bhatti, I Ali Ismaili, D Nawaz Hakro இவர்கள் இங்கும் “Phonetic-based sindhi spellchecker system using a hybrid model” பதிவு செய்தனர் [PDF] psu.edu
  5. சொல்திருத்திகளின் அமைப்பை பற்றி ஒரு வார்ப்பு/எல்லை கணக்கெடுப்பை 2012-இல் “Spell checking techniques in NLP: a survey ” என்று N Gupta, P Mathur – International Journal of Advanced …, 2012 இவர்கள் வளியிட்டனர்.

இவை அனைத்துமே ஒருவகையில் – புதியவைஅல்ல; மொழியியலில் – அதுவும் கணினிவழி மொழியியலில் – 1980-களில் இருந்தே ஆய்வுகள் வளிவந்திருக்கின்றன். இவற்றில் இன்றும் பயன்படுத்தும் edit-distance, suggestion generation போன்ற செயல்முறைகளை அவர்கள் கண்டறிந்து புதுமை செய்தனர். எ.கா. J. L. Peterson, Computer programs for detecting and correcting spelling errors.

நாங்களும் எங்களது சிரிய பங்களிப்பான ‘சொல்திருத்தி’ என்ற ஒபன் தமிழ் படைப்பை இங்கு பதிவு செய்தும் தமிழ் இணையமாநாடில் 2018-இல் பதிவு செய்தோம்.

இத்தகைய பதிப்புகள் என்ன சொல்கின்றன ? எப்படி எப்படி தானியங்கியாக ஒரு சராசரி கணினி ஒரு 12-ஆண்டு கடின பயிற்சி இல்லாமல் மொழியை திருத்தம் செய்கின்றது ? என்ன விளையாட்டா இருக்குதேன்னு நிங்கள் நினைக்கலாம் ஆனால் அனைத்தும் அல்கோரிதங்களின் மகிமை – ஒரு செயல்முறைகணிமையில் சாத்தியமானதுவே என்று அடுத்த தொடரில் பார்க்கலாம ?

ஆமவடை

ஏற்கணவே பதிவு செய்த  இடத்தில் இருந்து தொடருவோம்:

ஆமவடை
படம் 1: ஆமவடை

Corollary 2 of  Theorem 3: ஒரே சொல்லில் எழுத்து இரடிக்கப்பட்டால் அந்த சொல் டோரசில் ஒரு சுழலுடன் [loop] கொண்டபடி அமையும்.

Lemma 2:  படுக்கவசமாகவும், நிமிர்ந்துவசமாகவும் அமைகப்பட்ட சொர்கள் மொழியில் இல்லாதவை.

Corollary 3 or Theorem 3: டோரசில் படுக்கவசமாகவும், நிமிர்ந்துவசமாகவும் பாதைகள்/எழுத்துக்கள் இல்லாதவை.

Theorem 4: ஒரு அகராதியில் உள்ள சொர்கள் அனைத்தையும் டோரசில் பிரதிபலித்தால் அந்த குறுக்கிடும் இடங்களின் [intersecting points] ஒன்று அல்லது மெர்பட்ட சொற்களை] எண்ணிக்கை அளவை மிக குறைவாக்கும் வண்ணம் அமைக்க முடியாது. அதாவது ஒரு அகராதியின் சொற்கள் அனைத்து எவ்வித அமைப்பில் உள்ள டோரசானாலும் சரி அதன் குறுக்கிடும் இடங்களின் எண்ணிக்கை மாராது. இது ஒரு மாறிலி [invariant].

Corollary 1 of Theorem 4: மேர்கண்ட டோரசில் [அதன் ஒரு பிரதிபலிப்பில் – ‘அ,ஆ,இ,ஈ, … ,ஒ,ஓ,ஔ‘ என்றும் ‘கசடதபரயரலவழள – ….’  என்றும் வரிசையிலோ, அல்லது வேறு பரிமாணங்களில்  அடுக்கியிருந்தால்] ஒவ்வொரு அகராதிக்கும் ஒரு சிரப்பான குறுக்கிடும் இடங்களின் எண்ணிக்கை கிடைக்கும். இந்த எண் அகராதியின் கையொப்பம் [signature] என்றும் சொல்லாம்.

Theorem 5: டோரசில் உள்ள ஓவ்வொரு அகராதி சொல்லும் ஒரு பாதை என்று கொள்ளலாம். சொல்லின் தொடக்க எழுத்து  பாதையின் தொடக்கத்தையும், சொல்லின் கடைசி எழுத்து பாதையின் முடிவையும் குறிக்கும்; பாதை திசைகொண்ட பாதையாக இருக்கும் – ஒரு அம்பு தொடக்கத்தில் இருந்து முடிவின் திசையில் வழி காட்டும். ஆகையால் அகராதியில் இல்லாத பாதைகள் பிழையாக எழுதப்பட்ட  அகராதி சொற்களுக்கு சமம், அல்லது அகராதியில் இல்லாத புதிய சொற்களுக்கு சமம்.

வாதம் [ஆதாரத்தின் தொடக்கமாக கருத்ப்படலாம்]:  டோரசில்ஒவ்வொரு சொல்லும் [அதன் பாதையும்] அகராதியில் உள்ள சொற்களாகவே இருக்கவேண்டும். Coding-theory / error correction codes theory படி இவ்வகை சரியான எழுத்துக்கள் உள்ள பாதைகள், சரியான சொற்களாகவும், தவான சொற்கள் [இல்லாத சொற்கள்] பிழையானவை என்வும் அமையும். இவ்வாரான சொற்கள் சரியானவையையின் சொற்பிழை எனவும் கருதப்பாடும்.

Corollary 1 of Theorem 5: மேர்கண்ட டோரசில் முழு அகராதி பிரதிபலிக்கப்பட்டதால், இதனைக்க்கொண்டு ஒரு சொற்பிழை திருத்தி செய்யலாம். பிழையான் சொல்லின் திருத்தம், அதன் நெருங்கிய தொலைவில் உள்ள சரியான் சொல் என்பதை நடைமுரைவிதியாகக்கொண்டு இதனை அமல்படுத்தலாம்.

Theorem 6: Tries எனப்படும் சொல்மரங்களைக்கொண்ட தரவமைப்பை டோரசில் குறியிட்டால், அது தொடர்பாதையாக ஒரே தொடக்கமும், பல பாதைமுடிவுகளையும் கொண்டதாக அமையும். இவற்றில் சில பாதைகள் சேரும் வகையில் முடிவுபெரும் வகையிலும் அமையலாம்.

படம் 2: Trie மரம் என்ற தரவமைப்பு. இதில் ‘to’, ‘tea’, ‘ted’, ‘ten’, ‘A’, ‘in’, மற்றும் ‘inn’ ஆகிய சொற்கள் இடம் பெற்றுள்ளன.

உதாரணத்திற்கு, படம் 2-இல் முடியும் நிலை நுனிகள் ‘n’ என்பவை டோரசில் வரும்பொழுது சேரும் வகையில் முடிவுபெரும் வகையில் அமையும்.

-முத்து.

அன்பழகன் வாத்தியார்

எனது தமிழ் ஆசிரியர் கேட்டார் ‘சவம்-னா இறப்பின் பின் உள்ள சடலம், என்பது தெறியாதா?’ அப்பதான் ‘அன்பே சிவம்‘ என்பதை ‘அன்பே சவம்‘ என்று அவசரத்தில் எழுதியது புலபட்டது.  அன்பழகன் சார், அவருக்கு இனிமையா இதை பாடம் கற்பிக்க மட்டும் ஒரு வாய்பாகதான் தெறிஞ்சிருக்கு. அப்ப எனக்கு edit-distance by one (சிவம் -> சவம்) அதனால் வந்த வினை என தெறியாது. அவர்கையில் கற்றது வாழ்வில் ஒரு நல்ல அனுபவம்.

Today’s blog topic is spell-checking.

cvymtb4veaavvse

It is well known that Bayesian methods can be used to correct spelling error (see Prof. Daniel Jurafsky & James H. Martin book chapter); the above example (‘அன்பே சிவம்’) with real-word error (i.e. error is made not in dictionary word but semantic error) can be easily corrected if we have word level bi-gram data and uni-gram data. This can easily be collected from Tamil Wikipedia data dumps, or Project Madurai. [Hint: project tip for engineering/math/cs students].

While letter level uni, bi and tri-gram data exist for Tamil in open-tamil project and part of my work at Tamil-TTS here, this remains to be not publicly available. Once this data – made available in public-domain – can be integrated, the various Tamil spell checkers in Tamil like Rajaraman’s Vaani, Dr. Vasu Renganathan’s, and our solthiruthi can make use of it. Potentially hunspell, aspell tools can be updated at their suggestion level modules to provide appropriate suggestions.

Future generations will never know of ‘அன்பே சவம்’. 🙂

முத்து,

San José, CA

திருத்த திருத்த … பிழைகள் ஒழிந்திட – spellchecker

இந்த பதிவில் ஏற்கனவே எழுதிய மயங்கொலி எழுத்துகள் பற்றிய பதிவில் (எப்படி மயங்கொலி பிழைகளை திருத்தம் செய்யலாம் என்பது பற்றி)  சிந்தனைகளை வழிமுறைபடுத்தி இங்கு பதிவு செய்கிறேன்.

இந்த பதிவில் எப்படி மயங்கொலி பிழைகளை சொல்திருத்தியில் நடைமுறைப்படுத்தி open-tamil-இல் செயல்படுத்துவது என்றும், இதன் நல்ல விளைவுகளையும் பார்க்கலாம்.

திருத்தம்

 

“தமிழ் திருத்தி” என்ற பெயரில் இந்த (web-based) வலை வழி இடைமுகம் காணலாம் [படம் 1].

தமிழ் திருத்தியில் “பளம்” என்றும் மற்ற இரண்டு சொற்களை (“காதள்”, “எலிதில்”) உள்ளீடு செய்து, சறிபார்க்க சொல்லலாம்.

விடைகளும் மாற்றங்களும் இங்கே! தவறான சொற்கள் சிகப்பு நிர கோட்டில் சுட்டி காட்டப்படும். இதனை விரைவில் open-tamil-இல் காணலாம்.

spell-checker-mayangoli-cases
படம்: எழுத்தாளர் சொற்களை செதுக்குகிறாள்; ஆனால் அவளுக்கு சில சொற்பிழை வந்துள்ளது. இவற்றை எப்படி அவள் நிவர்த்தி செய்தாள் ?

 

spell-checker-mayangoli-replace-1
படம் 2: முதல் சொல் மாற்றம் பழம், கனி

spell-checker-mayangoli-replace-2
படம் 3: இரண்டாம் சொல் “காதல்”

spell-checker-mayangoli-replace-3
படம் 4: மூன்றாம் சொல் “எளிதில்”