Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
63
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 38 Множества «в бою»

{––––– Ввод множества границ (чисел) –––––}

procedure ReadSet(var aFile: text; var aSet : TBoundSet); var k : integer;

begin

While not Eoln(aFile) do begin

Read(aFile, K); aSet:= aSet+[K];

end;

Readln (aFile);

end;

 

 

 

 

var

FileIn, FileOut: text;

 

 

 

R: TStateSet;

 

{ множество соседей (результат) }

 

SA, S : TBoundSet;

{ границы царства «A» и прочих }

 

State: char;

 

{ буква с названием очередной страны }

begin

{––––– Главная программа –––––}

 

Assign(FileIn, 'P_38_3.in'); Reset(FileIn);

 

Assign(FileOut, ''); Rewrite(FileOut);

 

R:= []; SA:=[];

State:='A'; { начнем с царства «A» }

 

ReadSet(FileIn, SA);

{ из первой строки читаем границы для «A»}

 

while not Eof (FileIn) do begin

{ цикл по странам }

 

State:= Succ(State);

{ буква следующей страны }

 

S:=[]; ReadSet(FileIn, S);

{ читаем границы страны }

 

{ если граничит с царством «A», добавляем к результату }

 

if S*SA <> [] then R:= R + [State];

 

end;

 

 

 

 

WriteCharSet(FileOut, R); Readln;

{ вывод результата }

end.

Close(FileIn);

Close(FileOut);

 

 

 

 

 

Программа Ника вычислила, что царство A соседствует с царствами B, D, F, I. Со временем проверка на местности это подтвердила.

Царь щедро наградил программиста, но история на этом не закончилась. О великом научном успехе скоро знала и последняя собака на материке. Но больше других этот успех заинтересовал купцов, плативших пошлины при пересечении границ. Они явились к Нику с предложением, от которого тот не смог отказаться. Хотите продолжения сказки? — оно ждёт вас в главах 49, 57 и 58.

Решето Эратосфена

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

273

Глава 38 Множества «в бою»

математических размышлениях. Греческий досуг оказался не таким уж пустым, — иные задачки, придуманные под ласковый шепот волн, не решены по сию пору! Одна из них — вычисление простых чисел.

Прежде всего, выясним, что это за числа? Простым называют число, которое делится без остатка лишь на само себя и единицу. Все прочие числа являются составными. Возьмем, к примеру, числа от 1 до 10 и подчеркнем среди них составные:

1 2 3 4 5 6 7 8 9 10

Здесь отмечены составные числа 4, 6, 8, 9 и 10, — они делятся без остатка либо на 2, либо на 3. Оставшиеся числа 1, 2, 3, 5 и 7 являются простыми.

Кто-то из греков задался вопросом: можно ли вычислить очередное простое число, если известны все предыдущие? Например, исходя из того, что числа 1, 2, 3 и 5 простые, определить следующее простое число (7). Как ни мудрили мудрецы, такой формулы или алгоритма пока не придумали! Но усилия в этом направлении породили целые отрасли математики, — вот такой полезный неуспех!

Размышлял над задачей и грек Эратосфен. Он тоже не решил её, однако нашел остроумный способ отсеивать простые числа, не превышающие некоторого числа N. Вот суть его идеи.

Положим, мы ищем простые числа не превышающие 20. Выпишем на морском песочке в ряд числа с 1 до 20. Первые два числа — 1 и 2 — простые, их не тронем, а среди остальных сотрем каждое второе, то есть 4, 6, 8 и так далее.

Затем находим первое нестертое число — это три. Сотрем каждое третье после тройки: 6, 9, 12, 15 и 18 (хотя часть из них уже стерта, лишний раз это сделать не повредит). Повторяя процедуру, находим следующее нестертое число — это пять. Стираем каждое пятое после пятерки: 10, 15, 20 (хотя все они уже стерты). Достигнув середины этого списка — числа 11, остановимся. Дальше двигаться нет смысла, поскольку на песке остались лишь простые числа.

Примечание. Если говорить точнее, лучше остановиться на числе, которое составляет корень квадратный из числа N, в данном случае это 5. Но для упрощения задачи мы будем обрабатывать больше чисел — половину ряда.

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

274

Глава 38 Множества «в бою»

1-й отсев чисел, кратных 2:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2-й отсев чисел, кратных 3:

1 2 3 * 5 * 7 * 9 * 11 * 13 * 15 * 17 * 19 *

Результат – простые числа:

1 2 3 * 5 * 7 * * * 11 * 13 * * * 17 * 19 *

А если бы Эратосфен жил в наше время? Стал бы он царапать на песке? Конечно, нет, — на что ж тогда компьютеры? Программа P_38_4 находит все простые числа, не превышающие 255, — роль песка исполняет множество чисел.

program P_38_4; { Решето Эратосфена }

var Simples : set of byte; { множество чисел } n, m : integer;

F : text; begin

Assign(F, 'P_38_4.out'); Rewrite(F);

Simples:= [2..255]; { Сначала множество полное } { Цикл вычеркивания составных чисел }

for n:=2 to (255 div 2) do begin

{ если число ещё не вычеркнуто } if n in Simples then

{ проверяем на кратность ему все последующие } for m:=2*n to 255 do

{ если остаток(m/n) равен нулю, то m – составное } if (m mod n)=0

{ и его надо вычеркнуть из множества} then Simples:= Simples – [m];

end;

{ Распечатка множества простых чисел }

for n:=2 to 255 do if n in Simples then Writeln(F,n); Close(F); Readln;

end.

Мелочь, а приятно

Одну из первых своих программ мы снабдили разумом попугая, научив повторять имя пользователя. После ввода имени в переменную S программа печатала:

275

Глава 38 Множества «в бою»

Writeln (’Здравствуй, ’+ S);

Сделаем её чуть умнее, научив отличать мальчиков от девочек. По крайней мере, для русских имен. У нас женские имена оканчиваются на буквы «а» или «я» (Анна, Светлана, Мария и так далее), чего не скажешь о мужских. Последнюю букву имени можно «выдернуть» в символьную переменную C таким оператором:

C:= S[Length(S)];

И теперь приветствовать пользователя можно так:

if (C=’А’) or (C=’а’) or (C=’Я’) or (C=’я’)

then Writeln (’Здравствуй, девочка ’+ S)

else Writeln (’Здравствуй, мальчик ’+ S);

Здесь проверяется совпадение переменной C с буквами верхнего и нижнего регистров, поскольку нельзя предсказать, в каком регистре будет введено имя. Условный оператор выглядит громоздко, но, призвав на помощь множество, мы упростим его:

if C in [’А’, ’а’, ’Я’, ’я’]

then Writeln (’Здравствуй, девочка ’+ S)

else Writeln (’Здравствуй, мальчик ’+ S);

Переменную C проверяем на попадание в множество символов. Согласитесь, этот вариант читается приятней.

Итоги

Если вовремя смекнуть, что имеете дело с множествами, сложные задачи, как по волшебству, превратятся в простые!

А слабо?

А) Напишите программу для решения директорских задач и повторите подвиг контрразведчика. Или слабо?

Б) На острове действовали забавные законы по части транспортных средств

— автобусов, грузовиков и легковушек. Во-первых, общее количество автомобилей на острове не должно было превышать 256. Автомобилям назначались номера с 0 до 255, при этом соблюдались следующие правила.

Номера, делившиеся без остатка на 7, назначались автобусам. Те, что делились без остатка на 5, назначались грузовикам, а все прочие — легковушкам. Например, номера 35 и 70 (они делятся и на 7, и на 5) доставались автобусам, а не грузовикам.

276

Глава 38 Множества «в бою»

Схожие правила применялись и к окраске автомобилей, а именно: если номер авто делился на 4, его красили красным, если на 3 — желтым, если на 2 — белым, а остальные автомобили красили черным.

Сформируйте три множества по классам автомобилей – автобусы, грузовики и легковушки. Вычислите количество машин каждого класса (Ответ: 37, 44, 175).

Сформируйте четыре множества по цвету автомобилей – красные, желтые, белые и черные. Определите количество машин каждого цвета (Ответ: 64, 64, 43, 85).

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

В) Полицейская база островного государства содержала номера угнанных автомобилей — числа от 1 до 255. Это был текстовый файл такого, например, вида:

120 31 16 25

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

Г) Генерация пароля длиной не менее восьми символов. В пароль входят символы трёх сортов: цифры, заглавные и строчные латинские буквы, например: «7UpJ7rsT», «PasCal701». Сделайте четыре варианта так, чтобы соблюдались следующие условия:

символ каждого сорта входит в пароль не менее двух раз, некоторые символы могут повторяться;

все символы пароля уникальны (примените множество);

символы одного сорта не соседствуют, например: «Pa7sCaL5», уникальность символов не требуется;

символы одного сорта не соседствуют и все символы уникальны.

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

277

Соседние файлы в папке delphi