Пример тупого перебора - или зачем нужна голова :)

Автор: Andy Bogdanov

Источник: https://unixdoc.ua-i.net/mirrors/unix.stat.burnet.ru/rexx/bruteforce.html

      Этот простенький скриптик перебирает пары букв английская-русская, русская-английская и при нахождении подобной пары заменяет английскую букву, схожую по написанию на русскую. Т.е. - перекодировка. Сложность задачи состоит в том что в тексте имеются не только русские слова, написаные с заменой отдельных букв схожими по написанию английскими, но и примеры задач написаные полностью на английском. Естественно, заменять их русскими - нежелательно. Скрипт написан для REXX под FreeBSD (rexx-imc), но с минимальными переделками пойдет и для любой другой версии.
-------rexman.cmd-------
#!/usr/local/bin/rexx -x

s = 1

rb.1='Е'
rb.2='Т'
rb.3='У'
rb.4='О'
rb.5='Р'
rb.6='А'
rb.7='Н'
rb.8='К'
rb.9='Х'
rb.10='С'
rb.11='В'
rb.12='М'
rb.13='е'
rb.14='у'
rb.15='о'
rb.16='р'
rb.17='а'
rb.18='х'
rb.19='с'
rb.20='Л'
rb.21='Д'
rb.22='Ж'
rb.23='Э'
rb.24='Я'
rb.25='Ч'
rb.26='З'
rb.27='Ъ'
rb.28='И'
rb.29='Ц'
rb.30='Ь'
rb.31='Б'
rb.32='Ю'
rb.33='Ё'
rb.34='й'
rb.35='ц'
rb.36='Ы'
rb.37='к'
rb.38='Ф'
rb.39='н'
rb.40='г'
rb.41='ш'
rb.42='щ'
rb.43='з'
rb.44='Й'
rb.45='ъ'
rb.46='ф'
rb.47='ы'
rb.48='в'
rb.49='П'
rb.50='п'
rb.51='Г'
rb.52='Щ'
rb.53='л'
rb.54='д'
rb.55='ж'
rb.56='э'
rb.57='я'
rb.58='ч'
rb.59='Ш'
rb.60='м'
rb.61='и'
rb.62='т'
rb.63='ь'
rb.64='б'
rb.65='ю'
rb.66='ё'

ab.1='E'
ab.2='T'
ab.3='Y'
ab.4='O'
ab.5='P'
ab.6='A'
ab.7='H'
ab.8='K'
ab.9='X'
ab.10='C'
ab.11='B'
ab.12='M'
ab.13='e'
ab.14='y'
ab.15='o'
ab.16='p'
ab.17='a'
ab.18='x'
ab.19='c'
/*
тупо расписываем массивы русских и английских букв
русские - все буквы (66)
английские - только схожие по написанию (19)
*/

do s=1 to 10
/*
этот цикл на 10 повторов пришлось сделать из-за невозможности перебрать все возможные
пары букв. ведь слово может выглядеть и так - KOHCTAHTЫ
кроме буквы Ы - все остальные английские. можно было сделать сброс переменных
в циклах чтоб после нахождения одной пары и замены начинать цикл заново - но
особого выигрыша все равно не будет... проще прогнать лишний раз...
*/
   aq = s+1
   file='rexxman's
/*
назначаем имя входного файла
*/  
   do while Lines(file) \= 0
      lin = LineIn(file)
      if Pos('0d'x,lin) \= 0 then
         if Pos('20200d'x,lin) \= 0 then lin = DelStr(lin,Pos('20200d'x,lin),3)
         else lin = DelStr(lin,Pos('0d'x,lin),1)
/*
это условие удаляет символ конца строки - нужно только для юникса
*/
      if Length(lin) < 2 then
         do
           Call LineOut 'rexxman'aq,lin
          iterate
         end
/*
здесь мы проверяем - а может строка пустая? зачем тогда искать там буквы :)
просто запишем эту строчку в выходной файл. для не-юникса условие будет < 3
*/
      do i = 1 to 19
         do m = 1 to 66
            do while Pos(rb.m''ab.i,lin) \= 0
           lin = Overlay(rb.m''rb.i,lin,Pos(rb.m''ab.i,lin))
/*
перебираем все возможные пары русская-английская буква и если нашли - то
перезаписываем исходную строчку, подставляя на место английской буквы соответствующую
русскую.
*/
        end
        do while Pos(ab.i''rb.m,lin) \= 0
           lin = Overlay(rb.i''rb.m,lin,Pos(ab.i''rb.m,lin))
/*
аналогично для английская-русская...
*/
        end
         end
      end
      Call LineOut 'rexxman'aq,lin
/*
если не нашли ничего - все равно запишем в выходной файл
*/
   end
end

exit
-------rexman.cmd-------

все! это конец... подумал Штирлиц. Но где же мой пистолет? :)))

у этого скрипта есть серьезный недостаток - он будет очень долго выполняться -
мне было лень думать, время было уже за 8 часов вечера, надо было идти домой и я
запустил этот скрипт на ночь...
придя утром я обнаружил что он закончился буквально за десяток минут до моего
прихода на работу :[       ] общее время обработки файла размером в 300 килобайт
на пентаре-100 составило около 11 часов :((( сначала я подумал что у меня
чем-то была занята машина - но ничего подобного! при повторном запуске все получилось
точно так же как и в первый раз... Пришлось почесать в затылке и написать новый скрипт...

-------rexman2.cmd-------
#!/usr/local/bin/rexx -x

file='rexxman'

Call Stream 'rexxman2','c','open'

do while Lines(file) \= 0
   lin = LineIn(file)
   if Pos('0d'x,lin) \= 0 then
      if Pos('20200d'x,lin) \= 0 then lin = DelStr(lin,Pos('20200d'x,lin),3)
      else lin = DelStr(lin,Pos('0d'x,lin),1)
   if Length(lin) < 2 then
      do
        Call LineOut 'rexxman2',lin
    iterate
      end
   do i=1 to Words(lin)
/*
делаем цикл длиной в количество слов в строке
*/
      if Pos('.', translate(Word(lin,i),'$.................................................................','.'||xrange('ю','Ъ')||xrange('ё','ё')||xrange('Ё','Ё'))) > 0 then
/*
преобразуем русские буквы в слове в точки - и если они там есть то...
*/
         do
           word_lin = translate(Word(lin,i),'ЕТУОРАНКХСВМеуорахс','ETYOPAHKXCBMeyopaxc')
       lin = Overlay(word_lin,lin,WordIndex(lin,i))
/*
преобразуем латинские буквы в слове в аналогичные русские и перезаписываем
исходную строку
*/
         end
   end
   Call LineOut 'rexxman2',lin
/*
если ничего не нашли - то все равно записываем строчку в выходной файл
*/
end

Call Stream 'rexxman2','c','close'

exit
-------rexman2.cmd-------

вот! этот скрипт работал всего 7 минут на той же самой машине :))) еще одно его достоинство - он обрабатывает такие сочетания как т.е. - буква е является здесь английской.
Теперь нам осталось поработать немного ручками и заменить предлоги с, В, ВО ну и некоторые слова которые можно набрать полностью английскими буквами – например MECTO - но в сравнении с основной работой - это немного...