Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

[ Миронченко ] Императивное и объектно-ориентированное програмирование на Turbo Pascal и Delphi

.pdf
Скачиваний:
68
Добавлен:
25.04.2014
Размер:
3.16 Mб
Скачать

361

Вообще говоря, существуют различные определения размерности, причем то, которое мы дали (размерность Минковского) – далеко не самое общее, причем оно обладает рядом недостатков. Например, некоторые счетные18 множества могут иметь ненулевую размерность. Существует определение размерности, которое дал Феликс Хаусдорф, которое не содержит подобных недостатков, однако размерность Хаусдорфа вычислять значительно труднее. Однако во многих случаях, в частности, для самоподобных фигур, как снежинка Коха, размерности Хаусдорфа и Минковского совпадают.

Фрактальной структурой обладают, например, корни растений: суммарная длина корней одной особи ржи = 622,8 км, а площадь поверхности корней = 640 м2 .

Теперь мы можем приступить к написанию программы, которая могла бы строить фракталы (приближенно, разумеется). Для этого рассмотрим понятие L-систем.

18.6. Построение самоподобных фракталов

Идея построения фракталов очень проста. Для того, чтобы рисовать изображения можно использовать так называемую черепашью графику. Черепаха характеризуется положением на экране (x, y) и углом поворота относительно оси ox - θ . Черепаха может двигаться вперед на некоторое расстояние r или поворачиваться на месте вправо или влево на угол α .

Для того чтобы черепаха могла нарисовать что-то на экране, надо написать программу на черепашьем языке (ЧЯ). Я буду придерживаться обозначений, принятых в книге Ричарда М. Кроновера «Фракталы и хаос в динамических системах. Основы теории»:

F

продвинуться вперед на расстояние r , прорисовывая след

b

продвинуться вперед на расстояние r , не прорисовывая след

[

открыть ветвь

]

закрыть ветвь

+

повернуться вправо на угол α

-

повернуться влево на угол α

Открыть ветвь означает сохранить положение черепахи (т.е. координаты и направление движения). Закрыть ветвь – это означает переместиться в точку, где находилась черепаха в момент, когда ветвь была открыта (т.е. вернуться к координатам, которые были сохранены в момент открытия ветви).

Итак: черепаха получает слово, состоящее из вышеперечисленных символов (программу на черепашьем языке), и выполняет содержащиеся в этом слове действия.

Теперь дело за малым – как построить слово, которое бы представляло собой пример фрактального изображения (т.е. некоторого приближения фрактала, т.к. бесконечное количество итераций отобразить нельзя).

Мы будем строить фракталы, которые начинаются из некоторой базовой фигуры, а потом на каждой итерации изменяются по определенным правилам, которые нам известны. Одним из таких фракталов является снежинка Коха.

18 Множество называется счетным, если его можно биективно отобразить на множество натуральных чисел.

362

Т.к. есть базовая фигура, значит, можно ее записать на черепашьем языке. Назовем эту строку аксиомой. Для острова Коха аксиома – равносторонний

прямоугольник, который на ЧЯ записывается так: F++F++F (величина угла равна π ).

3

На каждой итерации прямая заменяется следующей фигурой:

Это означает, что вместо буквы F надо подставить строку, которая задает эту фигуру:

F-F++F-F.

Эту строку будем называть подстановкой и обозначаться она будет в алгоритме neuf (neu - новый). Аналогично вместо b будет подставляться neub.

Например, остров Коха после первой итерации будет задаваться такой строкой: F-F++F-F++F-F++F-F++F-F++F-F

Рис 18.6. Снежинка (axiom = [F]+[F]+[F]+[F]+[F]+[F], neuf = F[++F][-FF]FF[+F][-F]FF)

Очевидно, что множество Кантора задается следующими параметрами:

ax = F neuf = FbF neub=bbb

Т.е. алгоритм построения фракталов таков: берем аксиому, затем вместо F подставляем в нее neuf, а вместо b подставляем neub.

18.7. Реализация черепашьей графики

Теперь мы напишем программу, реализующую предложенный алгоритм.

363

Рис. 18.7. Форма для примера по рисованию фракталов

Форма разделена на 2 части: место для рисования (компонент PaintBox типа TPaintBox во вкладке System) и панель (компонент Panel типа TPanel во вкладке Standard). На панель можно ставить компоненты также, как и на форму, причем их координаты устанавливаются относительно левого верхнего угла панели. У класса TPaintBox есть канва, на которой мы и будем рисовать. Можно было бы рисовать и на канве формы, но это не так удобно.

9 текстовых полей – это параметры, которые надо задать, чтобы получить фрактал. В Комбобоксе можно будет выбирать готовые фракталы (при этом будут заполняться лишь поля ввода, в которых должны находиться следующие параметры: axiom, neuf, neub, AnfWinkel, Dwinkel). Остальные параметры надо будет вводить самостоятельно.

Основных классов 3: SchildKröte (черепаха), FraktMacher (создатель фракталов), FraktMaler («рисовальщик фракталов»).

Fraktmaler – это класс, который в качестве своих компонентов содержит Schildkröte и FraktMacher. Он создан просто для удобства и лучшей структурированности.

Рис 18.8. Ковер Серпинского (axiom = F++F++F, Neuf = F--F++F++F--F)

364

Пример 3: Черепашья графика.

Яприведу в книге лишь 2 основные процедуры из этой программы:

1.Генератор фракталов GibFrakt (класса FraktMacher)

function FraktMacher.GibFrakt:string; var

z:string;

i,j:integer; begin

if n=0 then begin result:=ax; exit;

end;

z:=ax;

for i:=1 to n do begin result:='';

for j:=1 to length(z) do case z[j] of

'F': result:=result+nf; 'b': result:=result+nb; else

result:=result+z[j];

end;

z:=result;

end;

end;

1. Выполнение программы на черепашьем языке LeisteProgr (класса SchildKröte)

procedure SchildKrote.LeisteProgr(s:string;C:TCanvas); var

i,k:integer;

 

Arr:array of Lage;

 

AnfLage:Lage;

 

rwink:real;

 

begin

 

AnfLage:=self.SKLage;

//сохраняем текущее положение черепахи

C.MoveTo(L.x,L.y);

 

SetLength(Arr,100);

 

k:=0;

 

for i:=1 to length(s) do case s[i] of

'F': begin with L do

begin rwink:=ZuRadian(L.wink);

365

x:=round(x+r*cos(rwink));

y:=round(y+r*sin(rwink));

C.LineTo(x,y);

end;

end;

'+': L.wink:=L.wink+dteta;

'-': L.wink:=L.wink-dteta; 'b': begin

with L do begin

rwink:=ZuRadian(L.wink);

x:=round(x+r*cos(rwink));

y:=round(y+r*sin(rwink));

C.MoveTo(x,y);

end;

end; '[': begin

Arr[k]:=L;//загоняем в стек позицию черепахи k:=k+1;

end; ']': begin

L:=Arr[k-1]; //вытаскиваем их стека позицию черепахи

C.MoveTo(L.x,L.y); k:=k-1;

end;

end;

self.SKLage:=AnfLage; //устанавливаем исходное положение черепахи end;

Остальные процедуры, которые находятся вне основного модуля, имеют чисто вспомогательное значение. Что касается скорости работы этих двух алгоритмов, то скажу, что алгоритм построения черепашьего слова, который приведен выше, очень неэффективен. Можно легко придумать гораздо более быстрый алгоритм, что и предлагается вам сделать в упражнении 11.

Если посмотреть на алгоритм обработки черепашкой программы на ее языке, то видно, что единственной сложной математической операцией является вычисление косинуса и синуса. Поэтому для фракталов, у которых угол, на который изменяется

движение черепахи, можно представить в виде π , где n - целое число, отличное от n

нуля, можно ускорить алгоритм отрисовки фрактала, просто заранее вычислив все возможные значения cos(rwink), sin(rwink). Тогда объем вычислений сократится во много раз. Можете воспользоваться этим, чтобы ускорить алгоритм отрисовки черепахой фрактала.

Готовые фракталы, которые можно выбирать в комбобоксе, хранятся в файле 'FertigenFraktalen.txt' (т.е. готовые фракталы). Они хранятся в следующем формате:

Название фрактала

Axiom

Neuf

Neub

366

AnfWinkel

DWinkel

Вы можете, естественно, дописывать в файл собственные фракталы, и они будут в начале работы программы (см. обработчик FormCreate события формы OnCreate) загружаться из этого файла в комбобокс.

Фактически в основном модуле ничего особенного кроме подпрограммы, которая считывает фракталы из файла и обработчиков разных событий, нет.

Задачи

1.Создайте класс Damestein (шашка), напишите основные методы.

2.Создайте наследника класса Brett (SpielBrett – «доска для игры»), в котором изменится процедура рисования: кроме самой доски должна выводиться аннотация (т.е. координатная система). Систему координат возьмите из русских или стоклеточных шашек.

3.Напишите класс DameSpielBrett, наследника SpielBrett, в котором кроме информации о доске находились бы массивы шашек. У класса DameSpielBrett должен быть метод, позволяющий расставлять эти массивы шашек на доску.

4.Напишите класс KoordSys, в котором бы находилась вся необходимая информация для построения системы координат на плоскости. Нарисуйте на этой

системе

 

координат

 

график

функции

y = sin x и усеченные суммы

ряда

 

 

n

 

2n+1

 

 

 

 

 

 

 

 

 

 

y(x) =

(−1)

 

x

 

 

 

, т.е.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

n=0

(2n +1)!

 

 

 

 

 

 

 

 

 

 

y = x , y

 

= x

x3

 

,

y

 

= x

x3

+

x5

и т.д.,

и посмотрите, насколько точно

ряд

2

 

3

 

 

1

 

 

 

 

3!

 

 

 

3!

 

5!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

соответствует настоящим значениям синуса.

5.В главе рекурсия мы рассматривали задачу: как расставить n ферзей на доске размером n n так, чтобы они не били друг друга. Напишите программу, которая бы не только находила подходящие комбинации, но и некоторые из них (по желанию пользователя) рисовала на доске SpielBrett (см. задачу №2).

6.Тело веса P , брошенное с начальной скоростью v0 под углом α к горизонту, движется под влиянием силы тяжести. Найти уравнения движения тела (считая, что тело начинает движение из начала координат), и начертить график, используя класс KoordSys. Можете при желании расширить класс KoordSys, пополнив его методами вычерчивания графиков.

7.(!) Решить предыдущую задачу, если на тело действует кроме силы тяжести еще и сопротивление воздуха R = kPv , k - коэффициент пропорциональности тела. Нарисуйте график движения тела.

8.(!) Тело начальной массы m0 начинает движение из начала координат, и

движется под действием силы тяжести и реактивной силы. Пусть масса топлива

составляет

m0 / 2 ,

закон изменения массы

ракеты

задается выражением:

m(t) = m ekt ,

где

k

- некоторый коэффициент (например, 0.005 ),

скорость

0

 

 

 

 

 

 

истечения газов

постоянна, направлена под

углом α

к горизонту

и равна

u = 2000 м . Учтите, что когда топливо заканчивается, тело продолжает двигаться

с

367

под действием лишь силы тяжести. Найдите закон, по которому движется тело, и время движения тела до падения на землю. Начертите график, и сравните его с графиками, которые получились в предыдущих двух задачах.

9.Вычислите размерность множества Кантора.

10.Вычислите размерность пыли Кантора.

11.Алгоритм построения фракталов, использованный для построения слова для черепахи, очень медленный. Придумайте как можно более быстрый алгоритм генерации черепашьего слова.

12.Постройте аналог черепашьей графики для того, чтобы можно было бы рисовать сплошные фрактальные области.

368

Проект 6: Беовульф и Нибелунги

От криптографии перейдем к лингвистике. Одной из распространенных задач лингвистов и историков является расшифровка древних языков. Криптографы изначально предполагают, что противнику, который пытается расшифровать текст, может быть известен и метод кодировки, и тема сообщения, и язык, на которым оно написано, а не известен лишь ключ – в случае подстановочного шифра – это конкретная подстановка, с помощью которой был закодирован текст. У специалистов по древним языкам ситуация иная: алгоритм шифрования (т.е. язык) неизвестен. Поэтому надо использовать все данные о самом народе, чей язык изучается и сведения о родственных языках (если такие существуют).

Расшифровка значительно упрощается, если к текстам, написанным на неизвестном языке, есть переводы на другие языки (хотя бы 1). Разумеется, наличие таких текстов тоже совсем не гарантирует успеха.

Вам на рассмотрение я предлагаю следующую задачу:

У вас есть текст древнеанглийской эпической поэмы «Беовульф» и переводы его на 3 языка: английский, немецкий и русский. Я предполагаю, что древнеанглийским вы не владеете, но при этом кроме русского знаете либо немецкий, либо английский.

Древнейшая из найденных рукописей «Беовульфа» датируется Х веком н.э., однако считается, что эта поэма была написана в 8 веке н.э. В поэме повествуется о подвигах Беовульфа, конунга гаутов, – как он боролся с зломерзкими тварями на земле и на море, правил землями и защищал свой народ от нападений соседей.

Ниже вы можете прочитать первые 25 строк «Беовульфа» на староангл., англ., нем., русск. языках. Полный текст (английский и, в особенности, немецкий текст содержат комментарии к тексту).

Беовульф

Староанглийский

Hwæt! Wé Gárdena

in géardagum

þéodcyninga

þrym gefrúnon·

hú ðá æþelingas

ellen fremedon.

Oft Scyld Scéfing

sceaþena þréatum

monegum maégþum

meodosetla oftéah·

egsode eorle syððan aérest wearð

féasceaft funden

hé þæs frófre gebád·

wéox under wolcnum· weorðmyndum þáh

oð þæt him aéghwylc

þára ymbsittendra

ofer hronráde

 

hýran scolde,

gomban gyldan·

þæt wæs gód cyning.

Ðaém eafera wæs

æfter cenned

geong in geardum

þone god sende

folce tó frófre·

 

fyrenðearfe ongeat·

þæt híe aér drugon

aldorléase

lange hwíle·

him þæs líffréä

wuldres wealdend

woroldáre forgeaf:

Béowulf wæs bréme

--blaéd wíde sprang--

Современный английский

LO, praise of the prowess of people-kings of spear-armed Danes, in days long sped,

we have heard, and what honor the athelings won! Oft Scyld the Scefing from squadroned foes,

5from many a tribe, the mead-bench tore, awing the earls. Since erst he lay friendless, a foundling, fate repaid him:

for he waxed under welkin, in wealth he throve, till before him the folk, both far and near,

10who house by the whale-path, heard his mandate, gave him gifts: a good king he!

To him an heir was afterward born, a son in his halls, whom heaven sent

to favor the folk, feeling their woe

15that erst they had lacked an earl for leader so long a while; the Lord endowed him,

the Wielder of Wonder, with world's renown. Famed was this Beowulf: far flew the boast of him,

369

Scyldes eafera

Scedelandum in.

 

son of Scyld, in the Scandian lands.

Swá sceal geong guma

góde gewyrcean

20

So becomes it a youth to quit him well

fromum feohgiftum

on fæder bearme

 

with his father's friends, by fee and gift,

þæt hine on ylde

eft gewunigen

 

that to aid him, aged, in after days,

wilgesíþas

þonne wíg cume·

 

come warriors willing, should war draw nigh,

léode gelaésten:

lofdaédum sceal

 

liegemen loyal: by lauded deeds

in maégþa gehwaére

man geþéön.

25

shall an earl have honor in every clan.

 

 

 

Немецкий

 

 

 

 

 

 

Русский

Hört! Denkwürd'ger Taten

von Dänenhelden

 

Истинно! исстари

слово мы слышим

Ward

uns

viel

fürwahr

aus

der

Vorzeit

 

о доблести данов,

о конунгах датских

berichtet,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Wie Könige kühn

 

ihre Kraft erprobten.

 

 

чья слава в битвах

 

мечами добыта!

Der Garbensohn Scyld

 

hat oft grimme Feinde,

 

Первый – Скильд Скевинг, войсководитель,

Viel mutige Krieger

vom Metsitz verjagt

5

не раз отрывавший

 

вражьи дружины

Und Furcht verbreitet.

In früher Jugend

 

 

от скамей бражных. За все, что он выстрадал

Fand man hilflos ihn

auf,

doch

Heil

ersproß

 

в детстве, найденыш,

ему воздалось:

ihm:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Unterm

Wolkendach

wuchs er,

an

Würden

 

стал разрастаться

властный под небом

reich,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bis alle endlich

ihm untertan wurden,

 

 

и, возвеличенный,

силой принудил

Die am Wege

des

Wals

ihren Wohnsitz10

народы заморья

 

дорогой китов

hatten,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Und Zins dem Herrlichen

zollen mußten.

 

дань доставить

достойному власти

Ein Sprößling ward ihm

später geboren,

 

Добрый был конунг!

В недолгом времени

Ein holder Knabe,

vom Herrgott gesendet

 

сын престола,

наследник родился,

Dem Lande zum Trost:

das Leid erbarmt' ihn,

 

посланный Богом

людям на радость

Das die Dänen lange

erduldet hatten,

 

15

и в утешение,

ибо Он видел

Eines Oberhaupts ledig.

Dem Erben Scylds

 

их гибель и скорби

в век безначалия, -

Verlieh der leuchtende

Lebensspender

 

 

от Вседержителя вознаграждение,

 

 

от жизнеподателя благонаследие;

 

 

 

 

 

 

 

 

 

 

 

Blühende Ehren

und Beowulfs Ruhm

 

 

знатен был Беовульф,

Скильдово семя,

Erscholl weithin

in Schonens Gauen.

 

 

в датских владениях.

С детства наследник

So schenke in jungen

Jahren der Mann

 

20

добром и дарами

дружбу дружины

Vom Hort freigebig

im Hause des Vaters,

 

должен стяжать,

дабы, когда возмужает,

Daß willig im Alter

ihn wiederum stützen

 

соратники

стали с ним о бок,

Die kühnen Kämpen,

wenn Krieg entbrennt,

 

верные долгу, если случится война, -

Und mutig ihm folgen:

die milde Hand

 

 

ибо мужу

должно достойным

Wird überall

dem Edling frommen.

 

25

делом в народе

славу снискать!

Ваша цель – как можно дальше продвинуться в расшифровке древнеанглийского текста.

Написать программу, которая смогла бы сама установить значение всех или большинства слов неизвестного языка – очень сложно. Но это и не требуется. Часто случается, что решение некоторой задачи приводит к появлению огромного числа идей, которые сами по себе очень важны. Расшифровка неизвестных языков – одна из таких задач.

Счего начинать писать программу?

1.ПК может быстро составить список слов для всех 4-х текстов. Разумеется, перевод далеко не дословный, однако частотность появления многих слов будет примерно одинакова.

2.Можно использовать «Поиск сходных слов», причем двумя способами:

370

Искать слова, которые сходны в текстах на разных языках (можно учитывать при этом и их положение в тексте)

Искать словоформы одного и того же слова в неизвестном языке. Если текст

достаточно большой (в «Беовульфе» свыше 3000 строк) то, быть может, удастся установить некоторые правила грамматики.

Примеры схожести слов из разных языков: æþelingas - athelings – Edlingen

wolcnum – welkin – Wolken sende – sent – gesendet

fæder – father - Vater

В одном языке: geardagum - geardum

Даже сама частота встречаемости слов может уже сказать о многом. Например, артикли, которые есть в немецком и английском языках, отсутствуют в русском (сразу напрашивается вопрос, есть ли они в древнеанглийском).

Фактически, от вас как от программиста требуется создать как можно лучшего помощника лингвиста. Затем, я думаю, вам должно быть интересно самому выступить в роли лингвиста и попытаться разобраться в тексте. Проект не должен быть привязан конкретно к староанглийскому языку: желательно, чтобы вы могли бы без переписывания большей части программного кода применить программу для расшифровки текстов на других языках.

Можете, если хотите, вместо Беовульфа взять другой эпос, например «Песнь о Нибелунгах»:

Песнь о Нибелунгах, современный Hochdeutsch

Viel Wunderdinge melden | die Mären alter Zeit

Von preiswerthen Helden, | von großer Kühnheit,

Von Freud und Festlichkeiten, | von Weinen und von Klagen,

Von kühner Recken Streiten | mögt ihr nun Wunder hören sagen.

Es wuchs in Burgunden | solch edel Mägdelein,

Daß in allen Landen | nichts Schönres mochte sein.

Kriemhild war sie geheißen, | und ward ein schönes Weib,

Um die viel Degen musten | verlieren Leben und Leib.

Die Minnigliche lieben | brachte Keinem Scham;

Um die viel Recken warben, | Niemand war ihr gram.

Schön war ohne Maßen | die edle Maid zu schaun;

Der Jungfrau höfsche Sitte | wär eine Zier allen Fraun.

Es pflegten sie drei Könige | edel und reich,

Gunther und Gernot, | die Recken ohne Gleich,

Und Geiselher der junge, | ein auserwählter Degen;

Sie war ihre Schwester, | die Fürsten hatten sie zu pflegen.

Die Herren waren milde, | dazu von hohem Stamm,

Unmaßen kühn nach Kräften, | die Recken lobesam.

Nach den Burgunden | war ihr Land genannt;