Алгодром


11. Алгоритм, работающий с величинами

ЗАДАЧА:

  Составить программу для исполнителя Чертежник, рисующую "равнобедренный треугольник"
из квадратов (со стороной 40):

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

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

Тогда главный алгоритм будет иметь вид:
перемещение в начальную точку ->
рисование первого (верхнего) ряда (1 квадрат) ->
в начало следующего ряда (на "1 квадрат" назад и вниз) ->
рисование второго (среднего) ряда (3 квадрата) ->
в начало следующего ряда (на "3 квадрата" назад и вниз) ->
рисование последнего (нижнего) ряда (5 квадратов) ->
алг треугольник
нач
подход
ряд(1)
переход(1)
 
ряд(3)
переход(3)
 
ряд(5)  
кон


Уточняя процедуру ряд, мы вунуждены использовать цикл: только с его помощью можно организовать рисование k квадратов (k — аргумент алгоритма ряд), если значение k заранее неизвестно.
Цикл организован по номеру n, рисуемого квадрата:
инициализация ->
все ли квадраты уже нарисованы? ->
рисование квадрата ->
переход к следующему ->
номер следующего квадрата ->
 
алг ряд(арг цел k)
нач цел n
n:= 1
нц пока n<= k
квадрат
прыжок
    n:=n+1  
кц
кон


Так, разумеется, получается короче, чем если вынести последнюю команду вызова вспомогательного алгоритма квадрат за рамки цикла и, как следствие, избежать "лишнего" k-го прыжка.
Но сейчас нам предстоит расплачиваться за стремление к краткости записи.Если вернуться к главному алгоритму, то легко заметить, что теперь (из-за "лишнего" прыжка в конце рисования ряда) возвращаться при переходе надо на 1 квадрат дальше.
Придется переписать основной алгоритм и уже за одно подготовить его для записи с помощью цикла:
 
алг треугольник
нач
подход
ряд(1)
переход(2)
 
ряд(3)
переход(4)
 
ряд(5)
переход(6)
 
кон


Используем для сокращения записи последнего алгоритма цикл:
Для этого обратим внимание, что в повторяющейся группе команд вызова вспомогательных алгоритмов ряд(...) и переход(...) их параметры изменяются с шагом 2.
Обозначим фактический параметр процедуры ряд (количество квадратов, которые следует нарисоваь в соответствующем ряду) l (l=1,3,5), а параметр процедуры переходm (m=2,4,6).
В качестве параметра будущего цикла можно выбрать любую из этих величин (но, конечно, не обе сразу).
 
алг треугольник
нач цел l,m
подход
l:= 1
m:= 2
нц пока l<= 5
ряд(l)
переход(m)
    l:= l+2
m:= m+2
кц
кон


Последнее, что стоит сделать: попытаться обойтись одной вспомогательной величиной, а не двумя. Бросается в глаза простое соотношение l=m-1, которое, очевидно, справедливо при входе в цикл и сохраняется при каждой итерации. И хотя этого замечания уже достаточно, чтобы исключить из алгоритма любую из них, можно поступить и иначе.
Используем для организации цикла номер i ряда (i=1,2,3).
Заметим, что значения параметра l являются последовательными нечетными числами (l=1,3,5=2*i-1), а mчетными  (m=2,4,6=2*i).
Все, таким образом, можно свести к i — номеру рисуемого ряда.
 
алг треугольник
нач цел i
подход
i:= 1
нц пока i<= 3
ряд(2*i-1)
переход(2*i)
    i:= i+1
кц
кон


Забегая вперед, покажем как будет выглядеть наш алгоритм, если использовать цикл "для":  
алг треугольник
нач цел i
подход
нц для i от 1 до 3
ряд(2*i-1)
переход(2*i)
кц
кон