Тема уроку: "Використання циклу з післяумовою для розв'язування задач."

Мета уроку: Навчити використовувати цикл з післяумовою для розв'язування типових задач.
Тип уроку: Практичний.

На початку уроку рекомендується повторити типи циклів, формати опису та порівняльну характеристику циклів. Далі можна розглянути деякі типові задачі з використанням циклу з післяумовою.
Нагадуємо, що в усіх цих задачах кількість повторень заздалегідь невідома і тому, фактично, основним для розв'язку цієї задачі являється правильно підібрати умову виходу з циклу.

Задача №179.
Умова: На дверях ліфта висіло загрозливе попередження про те, що двері зачиняються самі в той самий момент, коли зайвий за вагою пасажир переступить поріг ліфта. Котрий пасажир постраждає, якщо ліфт витримує вагу не більше S кг, а вага пасажирів, що стоять у черзі до ліфта, дорівнює відповідно a1, a2, a3, … an?
В цій задачі зручніше використовувати цикл с післяумовою, тому що спочатку необхідно дати можливість "ввійти" пасажиру в ліфт, а потім перевіряти, чи витримає його ліфт. Умовою виходу з циклу буде перевищення сумарної ваги пасажирів, що увійшли в ліфт, деякого заданого критичного значення. Для зберігання ваги чергового пасажиру в цій задачі ми будемо використовувати одну й ту саму змінну (А), так як після перевірки вага пасажира нас вже не цікавить.

Program Example_179; 
Uses crt; 
Var N:word;       {I – номер пасажира, що увійшов у  
                   ліфт} 
    Sum,A,S:real; {Sum – сумарна вага пасажирів, що  
                   знаходяться в ліфті, A – вага  
                   чергового пасажира, що увійшов до  
                   ліфта, S – критична вага, що може  
                   бути піднята ліфтом} 
Begin 
  Clrscr; 
  Sum:=0;     {На початку роботи програми в ліфті  
  N:=0;        немає пасажирів} 
  Write(‘Введіть критичну вагу, що піднімає ліфт:  ’); 
  Readln(S); 
  Repeat 
    Write(‘Введіть вагу чергового пасажира:  ’); 
     Readln(А); 
     Sum:=Sum+А; 
    N:=N+1; 
  Until Sum>S; 
  Writeln(‘Постраждає ’,N,’-й пасажир.’); 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №181.
Умова: Капосний папуга навчився висмикувати у дідусі Василя волосся, яке ще залишилося у того на голові. Почавши з однієї волосини, він щодня збільшував порцію вдвічі. Через скільки днів дідусеві не знадобиться гребінець, якщо спочатку в нього на голові було аж N волосин?
Аналогічно попередній задачі, аналізувати наявність волосся на голові необхідно після того, як папуга вже висмикнув чергову порцію волосся. А "знущання" над дідусем скінчиться тоді, коли гребінець йому стане непотрібним, тобто кількість волосся на голові стане дорівнювати нулю.
Зверніть увагу, що в цій задачі змінна S використовується для підрахунку чергової порції волосся, що підлягає висмикуванню капосним папугою.

Program Example_181; 
Uses crt; 
Var S,N,Sum:longint;  {S – кількість волосся, що буде  
                       висмикнуто, Sum – кількість  
                       волосся, що залишилося в  
                       дідуся на голові, N –  
                       початкова кількість волосся} 
    Day:word;          {Day – номер дня, який папуга  
                        знущається над дідусем} 
Begin 
  Clrscr; 
  Write(‘Введіть початкову кількість волосся в дідуся  
         на голові:  ’); 
  Readln(N); 
  If N=0 
  Then writeln(‘Дідусь вже лисий, папузі нічого робити!’) 
  Else 
    begin 
      Day:=0; 
      Sum:=N;      
      S:=1;       {Початкова кількість волосся, що  
                   буде висмикнутою капосним папугою} 
      Repeat 
        Sum:=Sum-S;  {Зменшення дідусевого волосся} 
        S:=S*2;       
        Day:=Day+1;   {Підрахунок номера дня} 
      Until Sum<=0; 
      Writeln(‘Папуга знущався над дідусем ’,Day,’ днів.’); 
    End; 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №197(1).
Умова: Дано натуральне число n. Визначити кількість цифр у цьому числі.
Для розв'язання цієї задачі можна використати як цикл з передумовою, так і цикл с післяумовою. Однак, на наш погляд, другий варіант кращий, тому що навіть число "0" має у своєму складі одну цифру, а цикл з передумовою цей випадок пропустить. Справа в тому, що умовою виходу з циклу і в тому, і в другому випадку буде "зникнення" числа, тобто перетворення його на нуль після відкидання чергової цифри, а, якщо число с самого початку дорівнює "0", то цикл з передумовою не виконається ні разу, а цикл с післяумовою виконається обов'язково і підрахує одну цифру. Програма для розв'язання цієї задачі має наступний вигляд:

Program Example_197_1; 
Uses crt; 
Var N:longint;      {N – задане число} 
    Count:byte;     {Count – кількість цифр в числі} 
Begin 
  Clrscr; 
  Write(‘Введіть натуральне число: ’); 
  Readln(N); 
  N:=abs(N);    {Знаходження модуля числа для  
                 позбавлення від помилкового введення  
                 ненатурального числа} 
  Count:=0;     {Початкове значення кількості цифр} 
  Repeat 
     Count:=Count+1; 
     N:=N div 10;  {“Відкидання” останньої цифри  
                    числа після підрахунку} 
  Until N = 0; 
  Writeln(‘Кількість цифр в числі = ’,Count); 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №208(4).
Умова: Під час обчислення результатів деяких експериментів виникає необхідність отримання результату із заданою похибкою. Нехай результатом є нескінченна сума, що задається певною формулою, і відома похибка e (e > 0) для знаходження наближеного значення результату. Будемо вважати, що необхідна точність досягнута, коли додавання наступного доданку змінює суму на величину, меншу за e. Обчислити:

В даній задачі ми візьмемо додаткову змінну (S), яка буде зберігати наступний доданок до нескінченої суми. Умовою виходу з циклу буде зменшення величини цього доданку до значення e по модулю. Зверніть увагу ще на те, що вираз фактично призводить до знакочергування в нескінченній сумі, тому, щоб не знаходити степінь числа -1 можна враховувати номер доданку і, якщо він буде парним, віднімати черговий доданок, якщо ні - додавати.

Program Example_208_4; 
Uses crt; 
Var i:word;          {i – номер доданка}  
    S,Sum:real;      {S – черговий доданок, Sum –  
                      нескінченна сума} 
    Epsilon:real;    {Epsilon – задана похибка  
                      обчислень} 
Begin 
  Clrscr; 
  Write(‘Введіть значення похибки: ’); 
  Readln(Epsilon); 
  Sum:=0;         {Початкове значення дорівнює 0 для  
                   накопичення суми} 
  S:=1;        {Перший доданок нескінченної суми за  
                умовою дорівнює “1”} 
  i:=1; 
  repeat 
    if i mod 2 =0  
    then Sum:=Sum + 1/S 
    else Sum:=Sum - 1/S; 
    i:=i+1; 
    S:=S*i; 
  until 1/S<=Epsilon; 
  Writeln(‘Результат обчислень = ’,Sum:8:2); 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №209.
Умова: На скільки років необхідно покласти в банк суму Х грошових одиниць, щоб одержати суму N грошових одиниць (N > X), якщо банк нараховує 200% річних?
Очевидно, що умовою виходу з цього циклу буде отримання заданої суми грошей. Якщо за умовою задачі N > X, то кожну перевірку ми будемо виконувати після того, як до вкладеної суми додамо щорічний банківський процент.

Program Example_209; 
Uses crt; 
Var X,N:real;       {X – початковий вклад, N – бажана  
                     сума}  
    Rez:real;       {Rez – результуюча сума на  
                     рахунку} 
    Years:longint;  {Years – термін, протягом якого  
                     сума лежала в банку} 
Begin 
  Clrscr; 
  Write(‘Введіть початкову суму вкладу: ’); 
  Readln(Х); 
  Write(‘Введіть бажану суму вкладу: ’); 
  Readln(N); 
  If N<=X 
  Then writeln(‘Ви вже маєте бажану суму!’) 
  Else  
    Begin 
      Rez:=X; 
      Years:=0; 
      Repeat 
        Rez:=3*Rez;  {200% річних збільшують за рік  
                      вклад втричі} 
        Years:=Years+1; 
      Until Rez>=N; 
      Writeln(‘Ви отримаєте бажану суму через ’,years,’ років.‘); 
    End; 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №231.
Умова: Скласти програму, яка б допомогла працівникам ДАІ визначати кількість порушників перевищення швидкості на трасі, якщо відомо, що на даному проміжку траси встановлено обмеження на швидкість Vmax, а прилад фіксує швидкість автомобілів V1, V2, …, Vn.
В даній задачі ніяким чином не обумовлена умова виходу з циклу, тому є пропозиція: процес підрахування порушників необхідно закінчити тоді, коли чергове введене число буде недодатнім (дійсно, з від'ємною або нульовою швидкістю автомобіль рухатися не може). Для тимчасового зберігання швидкості чергового водія ми будемо знову використовувати одну змінну. Програма, що виконує задані обчислення, має наступний вигляд:

Program Example_231; 
Uses crt; 
Var V,Vmax:real;  {V – швидкість чергового водія,  
                   Vmax – максимально дозволена  
                   швидкість}  
    Count:longint;{Count – кількість порушників} 
Begin 
  Clrscr; 
  Count:=0;    {На початку роботи порушники відсутні}      
  Write(‘Введіть значення максимально дозволеної швидкості: ’); 
  Readln(Vmax); 
  Vmax:=abs(Vmax);   {Знаходження модуля для  
                      виключення помилки введення  
                      від’ємної максимальної  
                      швидкості} 
  Repeat 
    Write(‘Введіть значення швидкості чергового водія: ’); 
    Readln(V); 
    If V>Vmax then Count:=Count+1; 
  Until V<=0; 
  Writeln(‘Кількість порушників ’,Count); 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №234(2).
Умова: Дано натуральні числа n i a1, a2, …, an. Визначити кількість членів ak послідовності a1, a2, …, an, що кратні числу 3 і не кратні числу 7.
Взагалі цю задачу можна розв'язувати з використанням циклу з параметром, так як на початку роботи програми задається число n, що вказує кількість чисел, що вводяться. Але можна цю змінну використати для організації циклу з післяумовою і отримати інший розв'язок задачі, що вам і пропонується:

Program Example_234_2; 
Uses crt; 
Var n:word;       {n – кількість чисел, що вводяться}  
    a,count:word; {a – змінна, що зберігає чергове  
                   введене число; count – кількість  
                   чисел, що задовольняє заданій  
                   умові}  
Begin 
  Clrscr; 
  count:=0;     {На початку роботи кількість  
                 знайдених чисел дорівнює 0}      
  Write(‘Введіть кількість чисел, що будуть вводитись: ’); 
  Readln(n); 
  Repeat 
    Write(‘Введіть чергове число: ’); 
    Readln(a); 
    If (a mod 3 = 0) and (a mod 7 <> 0) 
    Then count:=count+1; 
    n:=n-1; 
  Until n<0; 
  Writeln(‘Кількість шуканих чисел = ’,count); 
  Readkey;	{Затримка зображення на екрані} 
End. 

Задача №251 (5).
Умова: Дано натуральне число n і дійсні числа a1, a2, …, an (a1 < > 0). Відомо, що в заданій послідовності є хоча б одне нульове значення. Розглядаючи члени послідовності, що розташовані до першого нульового члена, визначити середнє арифметичне членів.
Для розв'язку цієї задачі значення n, являється зайвим, якщо серед членів послідовності буде хоча б один нульовий елемент, тому ми враховувати цю змінну не будемо (хоча дітям можна пояснити, що у випадку відсутності нульового члена послідовності змінна n може використовуватись як додаткова для виходу з циклу, щоб виключити зациклення програми).
Зверніть увагу на те, що так як ми не знаємо, коли зустрінеться нульовий елемент, в програмі знаходиться сума всіх чисел послідовності (змінна Sum) та кількість введених чисел ( змінна сount), а після виходу з циклу вже знаходиться безпосередньо середнє арифметичне членів послідовності, як результат ділення суми на кількість чисел, зменшену на одиницю. Зменшення на одиницю відбувається тому, що фактично в тілі циклу буде підраховано один зайвий нульовий елемент (останній)

Program Example_251_5; 
Uses crt; 
Var count:word;   {count – кількість членів  
                   послідовності до першого нульового  
                   елемента}  
    a,Sum:real;   {a – черговий член послідовності,  
                   Sum – сума членів послідовності до  
                   першого “0”} 
    SA:real;      {SA – середнє арифметичне} 
Begin 
  Clrscr; 
  Sum:=0; 
  count:=0;    {Початкові значення дорівнюють “0”} 
  repeat 
    write(‘Введіть черговий член послідовності: ’); 
    readln(a); 
    Sum:=Sum+a; 
    count:=count+1; 
  until a=0; 
  SA:=Sum/(count-1);   
  Writeln(‘Середнє арифметичне = ’,SA:8:2); 
  Readkey;	{Затримка зображення на екрані} 
End. 

Домашнє завдання: