Стремление читать слова задом наперёд присуще даже самым отвратительным личностям, к коим мы, без тени сомнения, можем причислить Полиграфа Полиграфыча Шарикова из романа Михаила Булгакова Собачье сердце. Вспомните, как он начал своё восхождение к высотам низменных мыслей с причудливого слова Абырвалг, которое поначалу поставило в тупик доктора Борменталя и профессора Преображенского. Впрочем, они быстро догадались, что в оригинальном написании это была лишь вывеска магазина Главрыба, прочитанное Шариковым с конца.
Чему нас учит классика на данном примере? - Не всякое слово следует читать «по-арабски», дабы не смущать учёные умы!
Впрочем, истории известен и другой, весьма поучительный пример ретроградного чтения, опровергающий предыдущее утверждение. В порядком уже давние времена на Амуре село на мель судно под названием Сунь Ят- сен (китайский политик), его пытались стянуть за корму, но безуспешно. Это мероприятие продолжалось очень долго - пока один из матросов не повторил лингвистический подвиг Шарикова и не прочитал название судна с конца. Получилось Не стянусь! (только не придирайтесь к мелочам). Тогда попробовали зацепить трос за нос судна - и оно легко снялось с мели.
Кто мешает тебе выдумать порох непромокаемый?
Козьма Прутков
Второй пример лучше первого потому, что в результате прочтения названия судна наоборот получилась вполне осмысленная фраза, обернувшаяся практической пользой. Конечно, это всего лишь случайность, но кто запретит нам придумывать такие «двусмысленные» фразы? Однако больше известны другие фразы - их можно без ущерба для смысла читать и слева направо, и справа налево. Их называют палиндромами. Пожалуй, самый известный палиндром А роза упала на лапу Азора придумал Афанасий Фет, но мы знаем его только потому, что именно эту «волшебную» фразу диктовала Мальвина своему дубовому ученику Буратино. Легко проверить, что она читается точно так же и в обратную сторону. Почему и волшебная. В литературе вы найдёте множество примеров фраз-палиндромов (или более патриотично - перевёртышей), порой очень забавных и даже ненормативных. Но - придумывание таких афоризмов - настоящее искусство, которое совершенно не поддаётся алгоритмизации, поэтому мы поставим перед собой чисто техническую задачу - отыскать слова, которые не изменяются при чтении наоборот. Их тоже называют палиндромами, и вы наверняка знаете немало таких слов. Например, РОТОР, ШАЛАШ, КАБАК. Чтобы найти все такие слова, достаточно внимательно просмотреть словарь русского языка, но мы делегируем это пагубное занятие компьютеру, немного дополнив программу из предыдущего семинара.
Палиндромная программа
Итак, если вы ещё наигрались словами, давайте составим программу для поиска слов-палиндромов.
Объявим строковые переменные и присвоим им значения:
Очевидно, что если слово не изменяется при чтении задом наперёд, то stringl = string2. Велико искушение присвоить переменной string2 значение перевёрнутой строки string1. Например, так:
var
i: integer; len: integer;
len := length(stringl); for i:= 1 to len do
string2[len-i+1] := string1;
Затем сравнить строки и при их равенстве сделать вывод, что слово- палиндром найдено. Но можно поступить проще и ограничиться одной строковой переменной. Для этого достаточно заметить, что в слове- палиндроме одинаковые буквы расположены симметрично относительно середины слова, то есть достаточно сравнить первую половину букв со второй (если в слове нечётное количество букв, то букву в середине слова ни с какой другой сравнивать не надо).
for i:= 1 to len div 2 do
Остальное, как говорится, дело техники. После запуска программы загружаем нужный нам словарь:
// Загрузить словарь по выбору
procedure TfrmMain.sbtOpenFileClick(Sender: TObject);
begin
opendialog1.DefaultExt:=’txt’;
opendialog1.Filter:=’Text files (*.txt)|*.TXT’; opendialog1.InitialDir:= extractfilepath(application.exename); opendialog1.Title:=’Загрузите новый словарь’; if opendialog1.Execute then begin
filename:= opendialog1.filename; loadfile;
end
else
application.MessageBox (’Вы не загрузили словарь!’,NAME_PROG, MB_OK); end;
И сразу же создаём и сохраняем на диске словарь палиндромов:
procedure TfrmMain. LoadFile;
//имя файла хранится в переменной FileName
var
s : String;
F: TextFile;
i/j: integer;
len: integer;
flag: boolean;
begin
//Открываем файл для чтения:
{$i“}
AssignFile(F,FileName);
Reset(F);
{$i+}
if IOResultoO then{ошибка при открытии файла}
begin
filename;{слозарь не загружен!}
application.MessageBox ('Слозарь не загружен!',NAME PROG,
МВ_ОК);
end
else{зсё нормально}
begin
WordsAll:= 0; //всего слов загружено //считываем слова из файла: while not eof(f) do begin inc(wordsall);
Readln(F, S);
Spisok[WordsAll] := s; end;
CloseFile(F);
//записываем на диск словарь палиндромов:
s:= ExtractFileName(FileName);
s:= copy(s,1,length(s)-4) + '_pal.txt';
savedialog1.FileName:= s;
if not savedialog1.Execute then exit;
assignfile(f,savedialog1.filename);
rewrite(f);
lstProtokol.Items.Add (**); for i:=1 to WordsAll do begin s:= spisok; len:= length(s); flag:= true;
for j:= 1 to len div 2 do
if s[j] <> s[len-j+1] then begin flag:= false; break; end;
if flag= True then begin
lstProtokol.Items.Add (s);
lstProtokol.TopIndex:=lstProtokol.Items.Count-1; writeln (f, spisok); end; end;
Closefile(f);
(’Записан словарь: ’);
(ExtractFileName(savedialog1.filename));
Messagebeep(0); lstProtokol.Items.Add lstProtokol.Items.Add lstProtokol.Items.Add lstProtokol.Items.Add lstProtokol.Items.Add end; end;
Вы легко найдёте в этом коде наш алгоритм. Важно отметить, что мы добавили флаг, который первоначально устанавливаем в TRUE, но как только мы обнаружим несовпадение очередной пары букв, флаг сбрасываем и цикл for принудительно завершаем. После окончания проверки букв достаточно проверить состояние флага: если он установлен, то найден палиндром, который выводим в список на экране и записываем в файл. Вот и вся премудрость, зато каких «оборотней» мы отловили