    3. ТЕХНОЛОГИЯ «СВЕРХУ ВНИЗ»      27 

    3. Основная задача программирования и технология «сверху вниз» 

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

  28	ГЛ. 1. НАЧАЛА ПРОГРАММИРОВАНИЯ 

расположенного параллельно краям стола. Решая такую задачу, мы сначала,  
естественно,  должны придумать общую стратегию перемещения резака, 
выбрать, как и куда его двигать. Первым неформалъным описанием общей 
стратегии решения может быть, например, следующее: «Сначала переведем 
резак в левый  верхний угол  стола, а затем будем вести его вниз по первой 
колонке клеток и в каждой клетке проверять, есть под резаком металл или нет. 
Если мы найдем металл, то это и есть левый верхний угол листа металла,  и  
больше ничего делать  не надо.  Если  же  в  первой колонке мы металла не 
обнаружим, то проверим сверху вниз вторую колонку, Затем третью и т. д., 
пока не найдем металл». Этот план мы можем записать более формально в 
виде 

   программа в левый верхний угол металла 
  .  дано     : | на столе Резчика есть металл, резак поднят 
  .  получить : | резак в левом верхнем углу листа металла 
  . -----------
  ,   в левый верхний угол стола 
  ,   цикл пока РМ.резак не над металлом выполнять 
  .   .   перейти в следующую клетку 
  .   конец цикла 
  конец программы 

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

   программа перейти в следующую клетку 
   . дано     :     
   . получить: | резак в следующей клетке, если перебирать 
   .                   | их в порядке сверху вниз и слева направо 
   .----------------
   .   если РМ.резак не у нижнего края стола то РМ.шаг вниа 
   .   .    иначе
   .   .   цикл пока РМ.резак не у верхнего края стола выполнять 
   ,   .   .   РМ.шаг вверх 
   ,   ,  конец цикла 
   .   .  РМ.шаг вправо 
   .   конец если 
    конец программы 

    С чисто программистской точки зрения приведенный выше примep иллюстрирует 
новую возможность языка программирования

    3. ТЕХНОЛОГИЯ «СВЕРХУ ВНИЗ»	29 

возможность вызова из одной программы других. Встретив, например, в
программе «в левый верхний угол металла» строку «перейти и следующую клетку», 
Универсальный Выполнитель приостанавливает выполнение программы «в левый 
верхний угол металла», находит и выполняет программу «перейти в следующую 
клетку», после чкго продолжает выполнение программы «в левый верхний угол 
металла». 
    Естественно, что для того, чтобы Универсальный Выполнитель смor 
действительно перевести резак в левый верхний угол металла, ему надо дать 
текст, содержащий все три программы, а также указать, какую именно программу 
мы хотим выполнить. 
    Основная задача программирования. Как видно из приведенного нише примера, 
при создании программ удобно разбить, исходную задачу на подзадачи и записать 
программу, считая, что подзадачи решены. После этого можно для каждой 
подзадачи создавать программу отдельно (такие программы для решения подзадач 
часто называют подпрограммами). Естественно, что подзадачу можно в свою 
очередь разбивать на подподзадачи и т. д. Чем сложнее наша исходная задача, 
тем больше будет уровней иерархии и тем больше и конце концов получится 
отдельных программ. При современной методике программирования решение задачи 
среднего класса сложности может насчитывать несколько сотен таких программ. 
Чтобы  среди них можно было ориентироваться, программы группируют. Для такого 
объединения программ в группы существует специальной конструкция 
исполнитель—конец исполнителя. 
    То, что эта конструкция называется исполнителем, отнюдь не случайное 
совпадение. Выполнение любой программы состоит в проведении каких-то 
действий над какими-то объектами (например, при исполнении программы «в левый 
верхний угол металла» изменяется положение резака у Резчика металла). Вызов 
программы — это приказ на выполнение этих действий. Таким образом, группу 
программ можно (и это удобно) считать исполнителем с некоторой системой 
предписаний. Про самого исполнителя в этом случае говорят, что он реализован 
группой программ на базе каких-то других исполнителей, где каждая программа 
реализует некоторое предписание.
    Процесс разбиения исходной задачи на подзадачи с учетом (руппировки 
подзадач можно изобразить так: 

                        а)                     б)  
    исходная  ==>       промежуточные  ==>     базовые 
    задача              исполнители            исполнители

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

    ГЛ. 1. НАЧАЛА ПРОГРАММИРОВАНИЯ 30 

этих вновь придуманных исполнителей и отдельно б) — реализация 
промежуточных исполнителей (т. е. написание соответствующих программ) с 
использованием заданных заранее базовых исполнителей. Каждая из этих .задач 
может в свою очередь разбиваться на подзадачи и т. д. 
    Таким образом, за исключением, быть может, самого первого шага, перед нами 
будет стоять не задача написания одной отдельно взятой программы, а задача 
реализации одного исполнителя на базе каких-то других. Более того, на практике 
и исходная задача часто ставится не как написание отдельной программы, а как 
создание (реализация) того или иного исполнителя. 
    Заметим, что любого исполнителя можно рассматривать и описывать с двух 
точек зрения: внешней и внутренней. При использовании   исполнителя   нас   
интересуют его внешние свойства: какие у него есть предписания, что 
получается в результате их выполнения и т. д. Описание этих свойств, 
достаточное для использования исполнителя, называется внешним   описанием   
исполнителя. Внешнее описание исполнителя позволяет им пользоваться, но 
ничего не говорит о его внутреннем устройстве  (подобно тому как внешнее 
описание магнитофона содержит информацию о расположении кнопок 
«воспроизведение» и «запись», но не содержит информации  о числе моторов). 
    В терминах исполнителей можно сформулировать основную эадачу 
программирования:


    Основная задача программирования: 

    дано :       | Внешнее описание искомого исполнителя А,
                 | который надо создать, и внешнее 
                 | описание базового исполнителя E, 
                 | который считается существующим
    получить :   | Реализацию R( A , E ) - текст на языке
                 |  программрования, опичывающий 
                 |  функционирование 
                 |  А в терминах Е и позволяющий изготовить 
                 |  А при наличии Е

    При решении производственных задач текст R(A, E) оказывается ужасающе 
длинным — от нескольких тысяч до нескольких сотен тысяч строк. Создание такого 
текста представляет собой трудную задачу, для решения которой в настоящее 
время разработано несколько подходов. Один из таких подходов — это технология 
«сверху вниз». 
    Технология программирования «сверху вниз». Технология  (греч. ремесло 
+ наука) — совокупность   знаний   о   способах   и   средствах проведения  
производственных  процессов.  Программирование — про-

    3. ТЕХНОЛОГИЯ «СВЕРХУ ВНИЗ»     31 

цеcc создания  (производства)   текста,   описывающего  исполнителя с заданными 
свойствами.
    Мы уже видели, что основную задачу программирования удобно решать, 
разбивая ее на подзадачи с помощью промежуточных исполнителей. Технология 
программирования «сверху вниз» предлагает такое разбиение вести от 
исполнителя А (сверху) к исполнитюлю Е (вниз), т.е. при придумывании 
промежуточных исполнителей руководствоваться скорее тем, что надо сделать, 
нежели тем, на какой базе. Технологическая цепочка программирования «сверху 
вниз» выглядит следующим образом: 
     ________           ______                                  _________
    |        |          |     |                                |         |
    |   A    | -------> |   B | ---------> ....... ----------->|   E     |
    |________|     |    |_____|                          |     |_________|
                   |     _______                         |        ________
                   |    |         |                      |       |        |
                    --> | R(A, В) |                       -----> | R(Z,E) |
                        |_________|                              |________|


    где В, ,.,, Z — промежуточные исполнители, придуманные в процессе решения 
задачи (а точнее, их внешние описания). Стрелки на схеме показывают 
последовательность действий человека. 
    При этом решение основной задачи программирования — текст R (А, Е) 
—получается в виде композиции реализаций 

    R (А, Е) = R (А, В) * R (В, С) * ... * R (Z, E). 

    Композиция реализаций — это объединение текстов R(A, В), R (В, С) и т. д. 
в указанном порядке. 

    Шаг декомпозиции. 
   При использовании технологии «сверху вниз» производство текста R(A,E) 
состоит из последовательного применения операции 
     ________             ______                                          
    |        |           |        |
    |   X    |  -------> |   Y    |  
    |________|      |    |_____   |                                 
                    |      _______                                
                    |     |        |                               
                      --> | R(X, Y)|                               
                          |_______ |                                        

    начиная  с внешнего  описания  искомого  исполнителя  А и  до тех пор, 
пока  не дойдем  до существующего  базового исполнителя  Е. Эта операция 
называется шагом декомпозиции, является сердцем технологии «сверху вниз» и 
состоит в следующем: 
 
     Шаг декомпозиции: 
    дано	: | Внешнее описание исполнителя X 
 получить : | Реализацию X на базе придуманного намb 
                    | исполнителя Y и одновременно внешнее 
                    | описание этого исполнителя Y 

    При проведении шага декомпозиции (т. е. при придумывании Y)  
следует руководствоваться двумя требованиями:

    32   ГЛ. 1. НАЧАЛА ПРОГРАММИРОВАНИЯ 

    1) локальное: как можно большую часть работы надо переложить на плечи 
нового исполнителя — на Y; 
    2) глобальное: шаг декомпозиции должен приближать нас к Е (т. е. Y должен 
быть «ближе» к Е, чем X). 
    Замечание 1. Как правило, при проведении шага декомпозиции исполнитель X 
реализуется на базе не одного исполнителя Y, а нескольких, например Y1, Y2. В 
результате шага декомпозиции возникают внешние описания этих исполнителен и 
одна реализация R(X,Y1,Y2): 

     ________               ______                                          
    |        |              |      |
    |   X    |  ------->    | Y1   |  
    |________|     |        |______|                                 
                   |      __________                                
                   |     |          |                               
                     --> |     Y2   |                               
                   |     |__________|                                        
                   |      ____________
                   |     |            |
                     --> | R(X, Y1,Y2)|                               
                         |____________|                                        


    Таким образом, в формуле для шага декомпозиции следует понимать Y как 
обозначение вектора (Y1, ..., YN). Если нарисовать технологическую цепочку без 
использования векторных обозначений, то стрелки, соединяющие внешние описания 
исполнителей, будут напоминать дельту большой реки, впадающей в «море» базовых 
исполнителей Е = (Е1, .... ЕК) (рис. 3.1). 
    Замечание 2. При проведении шага декомпозиции можно использовать 
исполнителей, внешние описания которых либо были заданы (например, Е1, ,.., 
ЕК), либо получены ранее, на предыдущих шагах декомпозиции. 
    Замечание   3.   В   результате   проведения   очередного   шага 
декомпозиции  внешние описания  придуманных  ранее  исполнителей могут быть 
уточнены или изменены. Более того, дойдя до какого-то места,   мы   можем   
увидеть,  что   придуманная   иерархия   промежуточных исполнителей неудачна, 
что какой-то исполнитель не реализуется или реализуется чересчур сложно. В 
этом случае приходится возвращаться на сколько-то шагов декомпозиции назад и 
начинать сначала. Таким образом,  программирование  является,  вообще  
говоря, итеративным (повторяющимся) процессом. Приведенная выше 
технологическая  цепочка является идеализацией и  описывает  процесс 
программирования без таких возвратов, 
    3амечание 4. Технология «сверху вниз» включает в себя еще и 
способы и средства контроля качества продукции (т. е. текстов R(A,В), R(B,С) и 
т, д.) на всех стадиях ее изготовления. Хотя на практике затраты на контроль 
качества — так называемые тестирование и отладку — зачастую соизмеримы с 
затратами на создание продукции, мы эти вопросы рассматривать не будем, 

    3. ТЕХНОЛОГИЯ  «СВЕРХУ  ВНИЗ»	  33

    Замечание 5. Имея реализацию R(A,E) и базового исполнителя Е, можно 
подключить Е к Универсальному Выполнителю и дать Универсальному Выполнителю 
текст R(A, E). В результата получится реально функционирующий исполнитель А, 
Мы, однако

    Рис.  3.1.  Иерархия  исполнителей  в  виде  «дельты  большой  реки» 

занимаясь программированием, будем интересоваться вопросами создания не 
самого исполнителя А, а лишь текста R(A, E). 
    Пример разработки программы по технологии «сверху вниз»*). Заставим теперь 
наш станок с ЧПУ — Резчика металла — заняться делом. Пусть требуется из листа 
металла нужного формата изготовить сито со структурой, изображенной на рис, 3.2. 
    Будем считать, что сито должен изготовить специальный исполнитель 
«Резчик сита» с одним-единственным предписанием «изготовить сито». 
Реализовать этого исполнителя (А) надо на базе базового исполнителя «Резчик 
металла» (Е) — его описание было приведено в разд. 1.	' 
    Размеры каждой ячейки сита — 60*60 шагов (клеток) Резчика Металла. В 
крайних ячейках верхнего и нижнего рядов проделы-

    *) Термин «разработка программы» сложился исторически и означает
реализацню программы или исполнителя на базе других исполнителей.

    2    А. Г, Кушниренко, Г. В, Лебедев 

    34	ГЛ. 1. НАЧАЛА ПРОГРАММИРОВАНИЯ 

ваются четыре отверстия для крепления сита. В крайней правой ячейке 
нижнего ряда, кроме того, проделывается отверстие, которое обеспечивает 
правильную ориентацию сита при монтаже. Во 

    Рис. 8.9. Сито

всех внутренних ячейках проделываются рабочие отверстия. Такии образом, 
имеем три типа ячеек с отверстиями (рис. 3,3), 


    Рис.  8.3.  Типы   ячеек с  отверстиями 

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

                     Резчик сита ==>  X и R(Резчик сита, X). 

    Попробуем придумать X. Первое требование, которым надо руководствоваться 
при таком придумывании, - переложить как можно большую часть работы на X.
Идеальным с этой точки зрения является исполнитель, который умеет делать сито 
целиком от начала до конца сам. Однако это и есть Резчик сита. Для того чтобы 
не получить тавтологии, надо помнить и про второе требованиё. X должен быть 
«ближе» к Е, чем А. 
    Посмотрим на сито и постараемся найти в нем максимально крупные (первое 
требование) образования, структуры, которые, однако, были бы меньше, чем сито 
в целом (второе требование). Легко видеть, что сито состоит из ячеек, рядов 
ячеек и колонок ячеек. Поскольку надо искать максимально крупные образования, 
то мы должны выбирать между рядами и колонками ячеек, а сами ячейки, как более 
мелкие, не рассматривать. Для выбора между рядами и колонками у нас нет 
никаких аргументов «за» и «против», поэтому возьмем наобум первое, что придет 
в голову, скажем ряды. 
    Попробуем теперь изготовить сито, считая, что у нас есть исполнитель, 
обрабатывающий ряды целиком (назовем этого исполнителя «Обработчик рядов»). 
Как это делать? Разумно обрабатывать последовательно ряд за рядом сверху вниз, 
начиная с верхнего. Будем считать, что в начале обработки ряда резак находится 
в левой перхней клетке ряда (в начале ряда). 
    Для того чтобы при переходе от ряда к ряду резак не надо было двигать, 
будем считать, кроме того, что в конце обработки ряда резак располагается в
начале следующего ряда. Это положение — клетку под левой нижней клеткой ряда — 
назовем концом ряда. Заметим, что все наши «будем считать» — это продолжение 
придумывания исполнителя «Обработчик рядов», а именно уточнение семантики 
его будущих предписаний. Сами предписания будем вводить «по ходу» там, где 
они понадобятся, 

    исполнитель Резчик сита 
    . СП:	
    .    1. изготовить сито 
    .
    . константы: 
    .    число рабочих рядов = 3 
    . используемые исполнители: 
    .    Обработчик рядов 
    конец описаний | —————— 

    программа изготовить сито 
    . дано    : | резак в начале (левой верхней клетке) заготовки и 
    .           | поднят 
    . получить: | сито изготовлено, резак в конце заготовки 
    .           | (в клетке под левым нижним углом заготовки) 
    .------------
    .   Обработчик рядов. начать работу 
    .   Обработчик рядов.обработать верхний ряд 
    .   цикл число рабочих рядов раз выполнять 
    .   . Обработчик рядов,обработать рабочий ряд 


    36  ГЛ. I. НАЧАЛА ПРОГРАММИРОВАНИЯ 


    .   конец цикла 
    .   Обработчик рядов.обработать нижний ряд 
    .   Обработчик рядов.кончить работу 
    конец программы 
    конец исполнителя |----------------------------------------

    Мы  здесь впервые встречаемся с конструкцией  исполнитель — конец 
исполнителя и с понятием константы.   Поэтому,   прежде чем идти дальше, 
поясним их. 
    Конструкция исполнитель — конец исполнителя состоит из двух разделов. В 
первом разделе (между строками исполнитель и конец описаний) приводится 
описание исполнителя в целом. Второй раздел (между   строками   конец описаний 
и   конец   исполнителя)   состоит просто из последовательно расположенных 
программ, реализующих предписания исполнителя.  Раздел описаний  может 
содержать различные подразделы. Подраздел СП  (система предписаний)  является 
обязательным. Смысл подразделов полностью соответствует их названиям.  
Подраздел константы используется для того, чтобы дать имена константам, 
используемым в исполнителе. После этого всюду ниже, вплоть до строки конец 
исполнителя, вместо констант можно использовать их имена.  Например,  встретив 
слова  «число  рабочих рядов» в процессе выполнения программы «изготовить 
сито», Универсальный  Выполнитель  заменит   их  на  значение  константы   
(3). Другие   возможные  подразделы   в   разделе  описаний   исполнителя 
будут пояснены по мере их появл ения. 
    Итак, вернемся к процессу  разработки  программы. Мы совершили первый 
шаг декомпозиции: 

    Резчик сита ==> Обработчик рядов и 
    		R (Резчик сита, Обработчик рядов)

    и получили реализацию R(Pезчик сита, Обработчик рядов) (это текст выше) и 
внешнее описание исполнителя «Обработчик рядов» (выпишем ниже). Поскольку 
Обработчик рядов еще не является базовым, то надо совершить очередной 
шаг декомпозиции; 

    Обработчик рядов ==> X и R (Обработчик рядов, X) 

    И опять, для придумывания X мы должны найти наиболее крупные образования, 
структуры, из которых состоят ряды. Это, несомненно, ячейки. Поэтому назовем 
следующего исполнителя «Обработчик ячеек». Будем обрабатывать ячейки в ряду 
слева направо и поэтому решим, что в начале работы всех предписаний 
Обработчика ячеек резак будет находиться в начале (левой верхней клетке) ячейки, а в 
конце работы — в конце ячейки {рис. 3.4), 


    Рис.  3.4 

    Попробуем реализовать предписание «обработать верхний ряд"

    Программа обработать верхний ряд 
    .  дано       :  | резак в начале верхнего ряда 
    .  получить: | верхний ряд обработан, резак в его конце 
    .-----------------
    .  Обработчик ячеек.крепежная ячейка 
    .  цикл число рабочих колонок раз выполнять 
    .  .  Обработчик ячеек.пустая ячейка 
    .  конец цикла 
    .  Обработчик ячеек.крепежная ячейка 

    В этот момент верхний ряд обработан, а резак находится в конце его 
последней ячейки. Для того чтобы обеспечить выполнение записанного в получить 
условия, надо переместить резак из конца последней ячейки в конец ряда. Эта 
подзадача возникнет, конечно, и при обработке рабочих рядов, и при обработке 
последнего ряда. Поэтому мы реализуем такое перемещение отдельной программой, 
и здесь запишем вызов этой программы:

    . встать в конец ряда 
   конец программы 

    Предписания «обработать рабочий ряд» и «обработать нижний ряд» реализуются 
аналогично. Запишем реализацию исполнителя «Обработчик рядов» в целом:

    исполнитель Обработчик рядов 
    СП: 
    .  1. начать работу 
    .  2. обработать верхний ряд 
    .  3. обработать рабочий ряд 
    .  4. обработать нижний ряд 


    гл   1. НАЧАЛА ПРОГРАММИРОВАНИЯ 38 


   .  — встать в конец ряда 
   .    
   .  5. кончить работу 
   .
   . константы: 
   .   число рабочих колонок = 7 
   .
   . используемые исполнители: 
   .    Обработчик ячеек 
   конец описаний |-----------------------------

    программа   начать   работу == Обработчик   ячеек,   начать   работу 
    программа обработать верхний ряд 
    .  дано    : | резак в начале верхнего ряда 
    .  получить: | верхний ряд обработан, резак в его конце 
    .  ---------------
    .  Обработчик ячеек, крепежная ячейка 
    .  цикл число рабочих колонок раз выполнять 
    .  .  Обработчик ячеек.пустая ячейка 
    .  конец цикла 
    .  Обработчик ячеек.крепежная ячейка 
    .  встать в конец ряда 
    конец программы 

    программа встать в конец ряда 
    . дано    : | резак в конце последней ячейки ряда 
    . получить: | резак в конце ряда 
    .   Обработчик ячеек.вниз на ячейку 
    .   цикл число рабочих колонок + 2 раз выполнять 
    .    .     Обработчик ячеек.влево на ячейку 
    .   конец цикла 
    конец, программы 

    Предписания   «обработать   рабочий   ряд»,  «обработать  нижний ряд» и 
«кончить работу» реализуйте самостоятельно. 

    конец исполнителя | ========================== 

    Минус перед «встать в конец ряда» в разделе описаний означает, что 
эта программа не является предписанием исполнителя «Обработчик рядов» и не 
может быть вызвана извне. Напомним, что программа «встать в конец ряда» 
возникла как решение подзадачи при реализации Обработчика рядов и 
используется локально только внутри этого исполнителя.

    8. ТЕХНОЛОГИЯ «СВЕРХУ ВНИЗ»     39 

    Программа «начать работу» записана в краткой форме, которая 
эквивалентна следующей:

    программа начать работу 
   . дано       : 
   . получить: 
   .   Обработчик ячеек.начать работу 
   конец программы 

    Мы совершили еще один шаг декомпозиции: 

    Обработчик рядов ==>  Обработчик ячеек и 
    R(Обработчик рядов, Обработчик ячеек) 

 и получили реализацию R (Обработчик рядов, Обработчик ячеек) и внешнее 
описание исполнителя «Обработчик ячеек» (сейчас выпишем). Поскольку 
исполнитель «Обработчик ячеек» еще не является базовым, надо совершить 
следующий шаг: 

    Обработчик ячеек ==> X и R(Обработчик ячеек, X) 


    Рис. 3.5. Рабочая ячейка, разбитая  на квадратики 

    И опять, для придумывания X мы должны найти наиболее крупные образования, 
структуры, из которых состоят ячейки. Легко видеть, что это еще не клетки 
Резчика металла, а более крупные единицы, имеющие размеры 15*15 шагов Резчика 
металла; назовем их «квадратиками» (рис. 3.5). 
    Поскольку никакого явно  выделенного  порядка обработки квадратиков при 
обработке, например, рабочей ячейки не предвидится, то будем считать, что в
начале и в конце обработки квадратика резак находится в erо начале (левой 
верхней клетке). 

    исполнитель Обработчик ячеек 
   . СП: 
   .    1. начать работу 
   .    2. крепежная ячейка 
   ,    3. монтажная ячейка 
   ,    4. рабочая ячейка 
   ,    5. пустая ячейка 
   . 
   .    6. вниз на ячейку 
   .    7. влево на ячейк r
   .    8. вправо на ячейку 


    40 ГЛ. I. НАЧАЛА ПРОГРАММИРОВАНИЯ 


    .   9. вверх на ячейку 
    .  10. кончить работу 
    .
    .  обозначения: 
    .   ширина ячейки == 4 | квадратика 
    .   высота   ячейки == 4 | квадратика
    .     
    .  используемые исполнители: 
    .   Обработчик квадратиков 
    конец описаний 

    Подраздел обозначения аналогичен подразделу константы. Встретив в тексте 
слова «ширина ячейки», Универсальный Выполнитель заменит их на текст, который 
записан после знака ==, в данном случае на 4. Таким образом, для 
Универсального Выполнителя обозначения и константы — суть одно и то же. 
Разница между этими понятиями существенна только для человека, который читает 
или изменяет текст программы. Запись 

    константы: 
       число рабочих колонок = 7 

подразумевает, что достаточно заменить 7 на другое число и без каких-либо 
изменений текстов программ исполнитель будет правильно работать с ситом новых 
размеров. Если это не так, т. е. если изменение значения может потребовать 
изменения текстов программ, ,то соответствующую величину надо задавать не в 
подразделе константы, а в подразделе обозначения. 

    программа начать работу == Обработчик квадратиков.начать работу 
    программа крепежная ячейка 
    .  дано       : | резак в начале ячейки 
    .  получить: I прорезано крепежное отверстие, резак в конце ячейки 
    .  Обработчик квадратиков.вправо на квадратик 
    .  Обработчик квадратиков.вниз на квадратик 
    .  Обработчик квадратиков.прорезать квадратик | Положение резака не меняется 
    .  Обработчик квадратиков.вверх на квадратик 
    .  Обработчик квадратиков.вправо на квадратик 
    .  Обработчик квадратиков.вправо на квадратик                           
    .  Обработчик квадратиков.вправо на квадратик                            
    конец программы 

    программа вниз на ячейку	! 
    . дано       : | резак в начале ячейки 
    . получить: | резак сместился на ячейку вниз	


    3. ТЕХНОЛОГИЯ «СВЕРХУ вниз»: 41 

    .   ---------------------------
    .   цикл высота ячейки раз 
    .   .   выполнять 
    .   .   Обработчик квадратик.ов.вниз на квадратия 
    .   конец цикла 
    конец программы 

    Остальные   предписания   втого   исполнителя   реализуйте   самостоятельно. 

    конец исполнителя |======================== 

   Мы совершили еще один шаг декомпозиции: 

    Обработчик ячеек ==> Обработчик  квадратиков и 
    R(Обработчик ячеек, Обработчик квадратиков) 

и получили реализацию R(Обработчик ячеек, Обработчик квадратиков) и 
внешнее описание исполнителя «Обработчик квадратиков» (выпишите его 
самостоятельно). Поскольку исполнитель «Обработчик квадратиков» еще не 
является базовым, то надо совершить следующий шаг декомпозиции: 

    Обработчик  квадратиков ==> X и R(Обработчик  квадратиков,  X) 

    И опять, для придумывания X мы должны найти наиболее крупные образования, 
структуры, из которых состоят квадратики. Это уже, конечно, клетки Резчика металла. 
    Проведите этот последний шаг декомпозиции и получите R(Обработчик 
квадратиков, Резчик металла) самостоятельно. 
    После этого задача будет полностью решена и будет получена реализация 

    R (Резчик сита, Резчик металла) =
	    R (Резчик сита. Обработчик рядов) 
	    * R (Обработчик рядов,  Обработчик ячеек) 
	    * R (Обработчик ячеек,  Обработчик квадратиков) 
	    * R (Обработчик квадратиков,  Резчик металла) 

    Напомним, что под композицией реализаций   (знак *)   понимается 
объединение текстов в один в указанном порядке.	, 

    ЗАДАЧИ И УПРАЖНЕНИЯ 

    1. Реализуйте нереализованные предписания Обработчика рядов и Обработчика 
ячеек (т. е. напишите соответствующие программы), 
    2. Реализуйте исподнителя «Обработчик квадратиков».

    42 ГЛ. I. НАЧАЛА ПРОГРАММИРОВАНИЯ 


    Рис. 3.6.  Сито,   окаймленное   пустыми   клетками 

    Рис. 3.7.  Сито,  рабочие   клетки  которого  окаймлены   пустыми' 

    Рис. 3.8.  Сито с крепежными отверстиями  по oven у  i\|m» 

    4. ПРОЦЕСС РАЗРАБОТКИ ПРОГРАММ 43 

    3. Модифицируйте R (Резчик сита, Резчик металла) так, чтобы из заготовки 
тех же размеров изготовить сито, аналогичное приведенному выше, но такое, что 
    а) все сито вокруг окаймлено полосой пустых ячеек (рис. 3.6); 
    б) рабочие ячейки окаймлены полосой пустых ячеек (рис. 3.7); 
    в) крепежные отверстия прорезаны в каждой граничной ячейке (рис. 3.8). 
    4. Напишите программы со следующими дано/получить; 
    а) дано     : | резак   над   металлом,   края   листа   совпадают о 
                  | краями клеток 
        получить: | резак в левой верхней клетке металла 
    б) дано     : |  резак над металлом,  края  листа совпадают  с краями клеток, лист лежит 
                  | далеко от краев стола 
        получить: |   из  листа  вырезана заготовка для сита максимального размера 
                          | (содержащая целое число ячеек) 
    в) (задача уровня сложности международных математических олимпиад): 
         дано  : | на столе Резчика металла очень далеко от краев стола лежит заготовка для 
                 | сита. В некоторых ячейках верхнего ряда и левой колонки прорезаны крепежные 
                 | отверстия. Известны константы «число рабочих рядов» и «число рабочих колонок». 
                 | Пользоваться можно только Резчиком металла, управляющими конструкциями   
                 | и подпрограммами 
       получить: | прорезаны рабочие отверстия на пересечениях тех рядов и колонок, в которых 
                 | есть крепежные отверстия