Тема уроку: "Розв'язування задач на складання алгоритмів з використанням функцій"

Мета уроку: Дати поняття про допоміжні алгоритми, типи допоміжний алгоритмів, оформлення підпрограм (функцій) мовою програмування Паскаль.
Тип уроку: Практичний.

На початку уроку рекомендується повторити теоретичний матеріал з теми "Допоміжні алгоритми": поняття допоміжного алгоритму, типи допоміжних алгоритмів, різниця між процедурами та функціями, формат опису функцій та процедур, передача параметрів у допоміжний алгоритм, фактичні та формальні параметри.
Після цього рекомендується розв'язати з учнями кілька задач.

Задача № 420.
Умова: П'ятеро бравих солдатів служили у війську під командуванням сержанта. Перед сержантом було поставлено завдання розробити стратегію визначення чотирьох вояк для штурму фортеці супротивника. Досвідчений сержант вирішив визначати найкращу четвірку за таким правилом: відношення суми ваги вояків до добутку їх зросту повинно бути максимальним. Хто з п'яти служак був удостоєний честі захищати своє військо?
Очевидно, що для збереження "параметрів" вояк (їх ваги та зросту) зручніше використовувати масив, так як в такому випадку обробку даних можна буде узагальнити. Крім того, очевидно, що не попаде на штурм солдат з найменшим значенням заданого добутку (ваги на зріст). Тому поставлена задача може бути розв'язана так: знайшовши вояку з найменшим добутком ваги на зріст, ми його залишаємо, а всіх останніх посилаємо на штурм.
Так як результатом роботи програми повинен бути номер солдата з найменшим добутком параметрів, підпрограму зручно оформити у вигляді функції. Тоді вхідним параметром допоміжного алгоритму буде масив з параметрами вояк, а вихідним - номер "найменшого" з них. Як передавати масив у підпрограму за допомогою формального параметру ми розглядали на попередньому уроці. Скористаємося першим з описаних методів (створення власного типу).
Опис використаних фактичних параметрів:
Soldat - двовимірний масив, що містить у першому стовпчику вагу відповідного солдата, а у другому - його зріст. Кількість рядків цього масиву, очевидно, дорівнює 5 (кількість солдат за умовою).
Number - номер солдата з найменшим добутком ваги на зріст.
Формальний параметр функції: - вхідний масив.
Заповнення масиву виконаємо в учбових цілях генератором випадкових чисел. При цьому не забуваємо, що вага солдата не може бути меншою за 50 кг та більшою 150 кг, а зріст - меншим за 1.5 м та більшим за 2.3 м.
Вихідна програма буде мати наступний вигляд:

Program Example_420; 
Uses crt; {Підключення бібліотеки} Mas 
Type 
T_Mas = array [1..5,1..2] of real; 
Function Solution (Mas:T_Mas):byte; 
var i:byte; 
Min:real; 
Begin 
Min:=Mas[1,1]*Mas[1,2]; 
Solution:=1; 
for i:=2 to 5 do 
if Min > Mas[i,1]*Mas[i,2] 
then  
begin 
Min:=Mas[i,1]*Mas[i,2]; 
Solution:=i; 
end; 
End; 
Var Soldat:T_Mas; 
Number,i:byte; 
Begin 
Clrscr; 
{Заповнення масиву та виведення його на екран} 
For i:=1 to 5 do 
begin 
Soldat[i,1]:=random*100+50; 
Soldat[i,2]:=random*0.8+1.5; 
writeln(Soldat[i,1]:8:2,Soldat[i,2]:6:2); 
end; 
writeln ('Не пішов на штурм ',Solution(Soldat),'-й солдат.'); 
Readkey; 
End. 
 

Задача № 432.
Умова: Використовуючи функцію max2(a,b), яка визначає максимальне з двох даних чисел, записати функцію max3(a,b,c), що визначає максимальне з трьох даних чисел, і організувати виклик цієї функції для обчислення суми найбільших значень трьох трійок довільних дійсних чисел.
Алгоритм пошуку максимуму з двох чисел являється стандартним і його написання, на наш погляд, не може викликати якихось непорозумінь. Написання алгоритму пошуку максимуму з трьох чисел також являється тривіальним і розв'язується за допомогою двох викликів функції пошуку максимуму з двох чисел в такім послідовності:
знаходиться максимум з двох чисел (наприклад, a та b)<.li>
знаходиться максимум з вже найденого максимуму та третього числа с.
За умовою необхідно знайти суму найбільших значень трьох трійок довільних дійсних чисел, тому результатом роботи програми буде значення змінної Rezultat, в якій ми будемо здійснювати накопичення суми.
Виклик функції виконаємо трьома способами. Перший раз для трьох змінних x, y, z, що будуть введені з клавіатури, другий - для трьох констант, що вибрані нами випадково, а третій - для деяких виразів (наприклад, знайти максимум модулів трьох чисел). Це робиться з навчальною метою, щоб показати, що у якості фактичних параметрів можуть бути не тільки змінні, а й константи або вирази (Зверніть увагу учнів на те, що константами або виразами фактичні параметри можуть бути тільки в тому випадку, коли відповідні формальні параметри являються параметрами-значеннями. Якщо ж формальний параметр є параметром-змінною, то відповідний фактичний параметр теж повинен бути змінною).
З урахуванням всього вище сказаного, програма, що виконує запропонований алгоритм, має наступний вигляд:

Program Example_432; 
Uses crt; {Підключення бібліотеки} 
Function Max2 (a,b:real):real; 
begin 
if a > b 
then Max2:=a 
else Max2:=b; 
end; 
Function Max3 (a,b,c:real):real; 
Var Max:real; 
Begin 
Max:=Max2(a,b); 
Max3:=Max2(Max,c); 
End; 
Var x,y,z,Rezultat:real; 
Begin 
Clrscr; 
writeln  ('Введіть три довільні числа: '); 
readln (x,y,z); 
Rezultat:=Max3(x,y,z); 
Rezultat:=Rezultat+Max3(2,-4.5,12.54); 
Rezultat:=Rezultat+Max3(abs(x),abs(y),abs(z)); 
writeln  ('Результат -> ',Rezultat:8:2); 
Readkey; 
End. 

Зверніть увагу учнів ще на те, що функція Max2 за умовою може бути вкладеною у функцію Max3 (так як в даному випадку використовується тільки нею). Тому оформлення функцій можна було виконати і так:

Function Max3 (a,b,c:real):real; 
Function Max2 (k,l:real):real; 
begin 
if k > l 
then Max2:=k 
else Max2:=l; 
end; 
Var Max:real; 
Begin 
Max:=Max2(a,b); 
Max3:=Max2(Max,c); 
End;  

Задача № 437.
Умова: Дано дійсні числа u та v. Визначити значення:
z = f(u,v) + f (u+v,uv) + f(u2,v2) + f(0.1,0.1)
де


На наш погляд, реалізація запропонованої функції являється тривіальною, але зверніть увагу на те, що у випадку, коли обидва числа дорівнюють 0, функція f(x,y) не може бути обчислена (виникає ситуація ділення на нуль). Цю перевірку можна виконати як в основній програмі, так і у підпрограмі. Але ми зробимо її в підпрограмі, щоб показати, що в таких випадках у якості результату функції можна зробити не безпосередньо обчислення, а ознаку того, що обчислення відбулися або не відбулися з якихось причин.
Тип результату функції в такому випадку зручно зробити булівський (значення true буде свідчити, що обчислення відбулися, а значення false, що ні). Результат же обчислень буде формальним параметром-змінною.
Програма, що виконує запропонований алгоритм, має наступний вигляд:

Program Example_437; 
Uses crt; {Підключення бібліотеки} 
Function F(x,y:real; var Rez:real):boolean; 
Begin 
if (x=0) and (y=0) 
then F:=false 
else 
begin 
F:=true; 
Rez:=(x+y)/(x*x+x*y+y*y)+x/(1+sqr(y))+y/(1+sqr(x)); 
end; 
End; 
Var u,v,R:real; 
Solution:Boolean; 
Begin 
Clrscr; 
writeln('введіть два числа: '); 
readln(u,v); 
Solution:=F(u,v,R)+F(u+v,u*v,R)+ 
F(sqr(u),sqr(v),R)+F(0.1,0.1,R); 
if F(u,v) = false 
then writeln('Помилкові вхідні дані.') 
else writeln('Результат обчислень -> ',R:8:2); 
Readkey; 
End. 

Задача № 452.
Умова: Дано координати вершин двох трикутників. Визначити, який з них має більшу площу.
Для розв'язання запропонованої задачі необхідно створити чотири функції:
1) Input - введення координат вершин трикутника та перевірка на правильність введення. Очевидно, що якщо користувач випадково чи навмисно введе координати таких точок, з яких не можна побудувати трикутник (наприклад, точки будуть лежати на одній прямій), то подальше розв'язування задачі неможливо. Тому зробимо вихідним параметром цієї функції теж булівську змінну (дивись попередню задачу), яка буде фіксувати, правильно введені координати точки (true) або ні (false). Значення цій змінній ми присвоюємо, враховуючи таке відоме всім учням правило: трикутник існує тоді і тільки тоді, коли довжина будь-якої його сторони буде менша за суму двох інших сторін.
Далі в основній програмі ми будемо контролювати значення, що повертає дана функція і примушувати користувача ввести правильні дані (примусове введення безпомилкових даних не обов'язково, але в даному випадку ми поставили за мету навчити учнів оформлювати алгоритми таким чином, щоб програма "не пропускала" неправильне введення).
2) Len - функція, що обчислює довжину відрізка за заданими координатами його кінців. Для виконання цього обчислення згадаємо, що довжину відрізка можна знайти за теоремою Піфагора:


де
z - шукана довжина відрізка;
(x1,y1), (x2,y2) - координати кінців відрізка.
3) S - функція, що визначає площу трикутника. Так як нам відомі тільки координати вершин трикутника, то площу зручно обчислювати за формулою Герона:


де
p - півпериметр трикутника;
a, b, c - сторони трикутника.
4) P - функція, що визначає периметр трикутника (ця формула очевидна, тому тут ми її наводити не будемо)
Причому для конкретно заданої задачі функція пошуку периметру трикутника може бути вкладеною у функцію пошуку площі трикутника.
Програма, що виконує запропонований алгоритм, має наступний вигляд:

 Program Example_452; 
Uses crt; {Підключення бібліотеки} 
{Обчислення довжини відрізка з координатами кінців (a,b) та (c,d)} 
Function Len (a,b,c,d:real):real; 
Begin 
Len:=sqrt(sqr(a-b)+sqr(c-d)); 
End; 
Function Input(var x1,y1,x2,y2,x3,y3:real):boolean; 
Var a,b,c:real; 
Begin 
writeln ('Введіть координати першої вершини:'); 
readln (x1,y1); 
writeln ('Введіть координати другої вершини:'); 
readln (x2,y2); 
writeln ('Введіть координати третьої вершини:'); 
readln (x3,y3); 
a:=Len(x1,y1,x2,y2); 
b:=Len(x1,y1,x3,y3); 
c:=Len(x3,y3,x2,y2); 
if (a>=b+c) or (c>=a+b) or (b>=a+c) 
then  
begin 
Len:=False; 
writeln ('Помилка! Повторіть введення:'); 
end 
else Len:=True; 
End; 
Function S (a,b,c:real):real; 
Function P (x,y,z:real):real; 
Begin 
P:=x+y+z; 
End; 
Var PP:real; 
Begin 
PP:=P(x,y,z)/2; 
S:=sqrt(PP*(PP-a)*(PP-b)*(PP-c)); 
End; 
Var x11,y11,x12,y12,x13,y13:real; 
x21,y21,x22,y22,x23,y23:real; 
S1,S2:real; 
Flag:Boolean; 
Begin 
clrscr; 
repeat 
writeln ('Перший трикутник:'); 
Flag:=Input(x11,y11,x12,y12,x13,y13); 
until Flag; 
repeat 
writeln ('Другий трикутник:'); 
Flag:=Input(x21,y21,x22,y22,x23,y23); 
until Flag; 
S1:=S(x11,y11,x12,y12,x13,y13); 
S2:=S(x21,y21,x22,y22,x23,y23); 
if S1>S2 
then  
begin 
writeln ('Більшу площу має перший трикутник.'); 
writeln ('Його площа дорівнює -> ',S1:8:2); 
end 
else 
if S2>S1 
then 
begin 
writeln ('Більшу площу має другий трикутник.'); 
writeln ('Його площа дорівнює -> ',S2:8:2); 
end 
else  
begin 
writeln ('Трикутники мають однакову площу.'); 
writeln ('Їх площа дорівнює -> ',S1:8:2);  
end;  
readkey; 
End. 

Зверніть увагу учнів на те, що результат роботи програми теж можна було оформити підпрограмою. Тільки в даному випадку це зручніше було б зробити процедурою.
Наприклад, так:

Procedure Output(S1,S1:real); 
Begin  
if S1>S2 
then  
begin 
writeln ('Більшу площу має перший трикутник.'); 
writeln ('Його площа дорівнює -> ',S1:8:2); 
end 
else 
if S2>S1 
then 
begin 
writeln ('Більшу площу має другий трикутник.'); 
writeln ('Його площа дорівнює -> ',S2:8:2); 
end 
else  
begin 
writeln ('Трикутники мають однакову площу.'); 
writeln ('Їх площа дорівнює -> ',S1:8:2); 
end; 
End;