четверг, 24 ноября 2016 г.

Використання власних функцій

Заняття 6
На цьому занятті я розгляну створення власних функцій, які використовуватимуться у програмах.
Нагадаю, що мова PYTHON є функціональною, тобто використовує для роботи з даними функції. До цього часу ми використовували стандартні функції, наприклад, int(), input(), print(), abs(), range(), map() тощо. Як видно із запису, всі вони після свого ім’я мають дужки, в яких записується їх аргумент чи аргументи, тобто ті величини, для яких визначається функція (якщо аргумент відсутній, то для функції береться той, що за замовчуванням). При звертанні до функції у програмний код підставляється її значення, наприклад, при виконанні запису
a=abs(b)
у змінну а записується значення модуля числа b.
Саме наявність великої кількості стандартних функцій зробило цю мову програмування зручною до використання і навчання. Крім цього є можливість підключення цілих модулів, кожен з яких містить від декількох до кількох десятків різноманітних функцій. Підключення цих модулів буде розглянуто пізніше, бо вони не входять до шкільної програми, але можуть використовуватися в олімпіадних завданнях. Але яка б не була кількість стандартних функцій завжди знайдеться та, яка потрібна до конкретної задачі, але вона не належить до них. Наприклад, для знаходження площі опуклого багатокутника шляхом розбивання його на трикутники з відомими сторонами, приводить до того, що потрібно використовувати формулу Герона кілька разів. Якщо буде відповідна функція, яка б за відомими трьома сторонами обчислюватиме площу трикутника, то вона значно полегшить розвязання цієї задачі. До того ж використання функцій розбиває велику задачу на менші підзадачі, які розвязуватимуть вже функції. Взагалі, використання функцій приводить до кращого розуміння ходу її розвязку і «читання» програмного коду, що є дуже важливим фактором майбутнього програміста, який буде працювати в команді.
Функцію до використання у програмі потрібно написати, причому у будь-якому місці програми, але до місця її виклику. Розглянемо написання функції Geron:
def Geron(a,b,c):
    p=(a+b+c)/2
s=(p*(p-a)*(p-b)*(p-c))**0.5
return s
      Перший рядок – це заголовок (назва) функції, що містить у дужках аргументи (довжини сторін трикутника).Починається рядок зі слова def. В кінці рядка ставиться двокрапка, а всі наступні рядки, що належать до функції, зміщені праворуч.
  Другий рядок містить обчислення півпериметра трикутника, а третій – обчислення площі трикутника.
     Четвертий рядок надає функції значення s (площі).
    Використаємо цю функції для розв’язання наступної задачі. У одному рядку дано 5 натуральних чисел: сторони чотирикутнка і довжина діагоналі, проведеної з вершини, спільної до перших двох сторін, до вершини, спільної для третьої і четвертої. Знайти площу паралелограма (див. рисунок).
     Весь програмний код матиме такий вигляд:

def Geron(a,b,c):
          p=(a+b+c)/2
s=(p*(p-a)*(p-b)*(p-c))**0.5
return s
a,b,c,d,m=map(int,input().split())
s=Geron(a,m,d)+Geron(b,m,c)
print(s)
     Кількість функцій, що можуть використовуватися в програмі необмежена, причому з однієї функції може викликатися інша. Якщо функція викликає саму себе, то вона називається рекурсивною, а сам спосіб такого виклику – рекурсією. Найпростіший приклад рекурсії є обчислення факторіалу n! (де n– невід’ємне число). Нагадаю, що n!=1∙2∙3∙…∙(n-1)∙n, або n!= (n-1)!∙n
    Запишемо програму, яка для даного числа визначає його факторіал
def fact(x):
         if x==1:
                   return 1
         else:
                   return fact(x-1)*x
n=int(input())
print(fact(n))
    У рекурсивній функції повинна бути прописана умова виходу з рекурсії (в нашому випадку при х=0). Поки не досягнута умова виходу, значення функції набуває значення, яке береться з наступного значення функції при іншому аргументі. Розглянемо покроково виконання цієї програми при n=4.
Після зчитування змінної n одразу викликається функція виведення значення print(), аргументом якої є значення функції fact(). Функція fact() викликається перший раз із аргументом 4, тобто значення змінної х у функції набуває значення 4. Пройшовши перевірку умови, значення цієї функції повинне набути значення fact(3)*4, але значення fact(3) ще треба обчислити, тому знову викликається ця сама функція, але вже з аргументом 3. Після перевірки умови значення функції стане рівним fact(2)*3, тобто fact(3)= fact(2)*3, а fact(4)= fact(2)*3*4. Наступний виклик функції відбувається з аргументом 1, тобто  fact(2)= fact(1)*2 або fact(4)= fact(1)*2*3*4. Останній крок завершує виклик функції (перериває рекурсію) і замість fact(1) виводить 1. Глибина рекурсії в даному випадку становить 4, бо стільки разів викликається функція. Для людини цей процес важко втримати в голові, а для комп’ютера просто, та і записується програма не досить складно.
       Ще одним із важливих прикладів використання рекурсії є знаходження найбільшого спільного дільника (НСД) двох чисел за алгоритмом Евкліда.  Дійсно, якщо число с є дільником чисел а і b, то він є дільником і їх різниці, тому НСД(а, b)= НСД(а, a-b) або НСД(а, b)= НСД(а, a % b). Якщо перший аргумент більший за другий, то можна записати так: НСД(а, b)= НСД(b, a % b). Так щоразу значення аргументів будуть зменшуватися, поки другий із них не стане дорівнювати 0. Отже, перший аргумент і буде відповіддю. Тому функція буде мати такий вигляд:
def nsd(a,b):
         if b!=0:
                   return nsd(b, a%b)
         else:
                   return а
Розглянемо кілька прикладів.

   Приклад 1.
   Знайти периметр багатокутника, заданого координатами своїх вершин. У першому рядку дано натуральне число n(n<100). У наступних n рядках дано по два цілих числа – координати наступної вершини багатокутника.
Вивести одне дійсне число, округлене до сотих, – периметр багатокутника.
Вхід                         Вихід
4                               19.79
-2 4
2 6
3 3
0 -2
def dist(x1,y1,x2,y2):                                #  опис функції з ім’ям dist                
    return ((x1-x2)**2+(y1-y2)**2)**0.5  # обчислення функції
n=int(input())                                            # зчитування кількості вершин
x1,y1=map(int,input().split())                  # зчитування координат першої вершини
x0=x1                                                       # запам’ятовуємо під іншими змінними
y0=y1                                                       #
p=0.0                                                 # початкове значення периметру в дійсному типі
for i in range(n-1):                                    #запуск циклу для решти n-1 вершин
    x2,y2=map(int,input().split())              # зчитування координат
    p+=dist(x1,y1,x2,y2)                            # збільшення периметру на значення функції
    x1=x2                          # тепер друга координата стане першою для наступної вершини
    y1=y2                                                  #
p+=dist(x1,y1,x0,y0) #додавання до периметру відстані між останньою вершиною і першою
print(round(p,2)) # виведення округленого до 2 знаків після коми значення периметра

      Приклад 2
    Знайти найменше спільне кратне (НСК) двох чисел. У двох рядках дано по одному натуральному числу. Вивести одне натуральне число – НСК цих чисел.
     Вхід             Вихід
     6                   24
     8
    Скористаємося відомим співвідношенням a*b=НСД(a,b)*НСК(a,b).
def nsd(a,b):
    if b!=0:
        return nsd(b, a%b)
    else:
        return a
x=int(input())
y=int(input())
print(x*y//nsd(x,y))
    
         Приклад 3.
     Опуклий п’ятикутник заданий координатами своїх вершин. Знайти його площу. У п’ятьох рядках дано по два дійсних числа – координати вершин п’ятикутника. Вивести значення площі п’ятикутника з точністю до тисячних.
       Вхід                       Вихід
       -2 4                        68.985
       -4 0.9
       0.42 -7.83
       5.5 -0.34
       2.34 5.3

      Приклад 4.
     Чотири бігуни бігають по колу довжиною 100 м. Перший пробігає одне коло за а секунд, другий – за b секунд, третій – за с секунд, а четвертий – за d секунд. Всі четверо починають бігти одночасно і не змінюють свою швидкість. Скільки метрів пробіжить перший спортсмен, коли вони знову зустрінуться всі в точці старту?
     У одному рядку через пробіл дано 4 натуральних числа, що не менші за 10 і не більші за 100, – час, за яких пробігає одне коло кожен спортсмен. Вивести одне натуральне число – відповідь на задачу.
     Вхід                       Вихід
    10 20 25 50            1000
    Пояснення прикладу: бігуни зустрінуться в точці старту через 100 секунд, бо за цей час перший спортсмен пробіжить рівно 10 кіл, другий – 5, третій – 4, а четвертий – 2. Тому перший спортсмен пробіжить 10*100=1000 метрів.
def nsd(a,b):
    if b!=0:
        return nsd(b, a%b)
    else:
        return a
def nsk(a,b):
    return a*b//nsd(a,b)
a,b,c,d=map(int,input().split())
s=nsk(nsk(nsk(a,b),c),d)          # час, за який одночасно досягнуть точки старту
print(s//a*100)


     Наступного разу я розгляну у статті використання списків, які більш відомі як масиви. До зустрічі.

понедельник, 26 сентября 2016 г.

Цикли в PYTHON

Заняття 5
До моменту вивчення циклів у школі  програмування для багатьох школярів є чимось складним, вони не розуміють переваг компютера над тими самими діями, виконаними «вручну». Звичайно, швидше учні розвяжуть задачі на слідування та розгалудження вручну, ніж напишуть програму і побачать результат роботи на екрані. Саме цикли показують переваги програмування над самостійним розвязуванням задачі. Отже, цикли …
На мові PYTHON є два види циклів: перелік і умовний. Розпочнемо з першого.
Цикл «перелік» записується так:
for i in range(n):
    тіло циклу
Змінна і пробігає значення певного діапазону записаного у функції range() і для кожного значення виконується деяка послідовність команд, яка називається тілом циклу. Як видно із запису, тіло циклу знаходиться правіше оператора for.
Розглянемо параметри функції range(). У наведеному записі змінна n задає інтервал від 0 до n-1 включно (всього n значень). Тобто, спочатку змінна і набуває значення 0 і для цього значення виконуються всі команди у циклі. Наступне значення змінної і є 1, потім 2, потім 3 і т.д., поки не досягне значення n, для якого цикл вже не виконується. У випадку запуску циклу не з нуля, то вводиться ще один параметр – початкове значення. Наприклад,
for i in range(3,n):
    тіло циклу
Значення змінної і розпочинається з 3, потім 4, і т.д. і закінчується n-1.
Якщо ввести ще один параметр, то отримаємо …Спробуйте зрозуміти самостійно :)
n=10
for i in range(3,n,2):
    print(i, end=’ ’)
Програма виведе результат:
3 5 7 9
Здогадалися? Змінна і змінює значення з певним кроком, який задається у третьому параметрі. Більш формально можна сказати так:
Функція range(x,y,d) задає інтервал від х до y-1 включно з кроком d, тобто x, x+d, x+2d, x+3d, поки не досягне значення, рівного y або більше, для яких вона не виконується. Якщо значення d<0, то повинно бути x>y. Наприклад, для виведення чисел від 100 до 1 потрібно записати так:
for i in range(100,0,-1):
    print(i, end=’ ’)

Розглянемо цикл з умовою. Цей цикл записується практично так само як і в PASCAL, тільки замість оператора do ставиться двокрапка
x=1
while x<10:
    print(x**2)
    x+=2
Програма виводить у окремих рядках квадрати непарних одноцифрових чисел. Зверніть увагу, що тіло циклу знаходиться правіше оператора while.
Звичайно, що умова циклу може бути як проста так і складна. Наприклад, для того щоб цикл повторювався, поки не дотягнеться певний результат, наприклад, поки позиція об’єкта (i, j) не співпаде з координатою (x, y), цикл запишеться так:
 while not(x==i and y==j):
    тіло циклу
Якщо під час виконання циклу потрібно відокремити окремий випадок, наприклад, не опрацьовувати його або вийти з циклу, то для цього використовуються оператори continue та break. Перший оператор переходить на початок циклу (до наступної ітерації), не опрацьовуючи дані, а другий виходить із циклу. Звичайно, для цих операторів всередині тіла циклу повинна прописана умова, для яких вона виконується.
Наприклад, при виведенні коренів рівняння (х^3+x^2-10x+8)/(x^2-6x+5)=0  в діапазоні [0;10] необхідно пропускати пошук і виведення кореня для тих випадків, коли знаменник дорівнює нулю, тому слід використати оператор continue.
for x in range(11):
    if x**2-6*x+5==0:
             continue
    if x**3+x**2-10*x+8==0:
             print(x, end=’ ‘)
Програма виведе число 2, бо  число 1 пропустить (знаменник дорівнює нулю), а корінь -4 не входить в область пошуку.
Коли ж потрібно зупинитися на відшукання лише одного кореня, то після його знаходження потрібно вийти із циклу за допомогою оператора break.
for x in range(-10,11):
    if x**2-6*x+5==0:
             continue
    if x**3+x**2-10*x+8==0:
             print(x, end=’ ‘)
                   break
Програма виведе число -4 і одразу вийде з циклу.
Розглянемо кілька прикладів.

Приклад 1.
Дано натуральне число n. Знайти n! (добуток всіх натуральних чисел, що не перевищує n, тобто 1*2*3*…*n).
Вхід                                              Вихід
6                                                    720

n=int(input())
p=1
for i in range(1,n+1):
    p*=i
print(p)

Приклад 2.
Дано натуральне число n. Знайти суму його цифр.
Вхід                                               Вихід
342                                                 9

n=int(input())
s=0
while n>0:
    s+=n%10           (знаходимо останню цифру і додаємо до суми)
n//=10                (відкидаємо останню цифру)
print(s)

Приклад 3.
Дано натуральне число n (n≤9). Вивести числові східці, у якій і-ий рядок складається із східців від 1 до і.
Вхід                                           Вихід
4                                                 1
                                                   12
                                                   123
                                                   1234

n=int(input())
for i in range(1,n+1):
    for j in range(1,i):
             print(j, end=’’)
    print(i)

Приклад 4.
Дано послідовність чисел по одному в кожному рядку, що закінчуються нулем. Знати середнє арифметичне їх значення. Число 0 обробляти не потрібно. Числа в послідовності є натуральними.
Вхід                                              Вихід
4                                                    5.5
5                                                
12                                              
1                                                
0

s=0
n=0
a=int(input())
while a!=0:
    s+=a
    n+=1
    a=int(input())
print(s/n)

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