NMIN101 Programování 1 NMIN102 Programování 2
2/2 Z ----2/2 Z, Zk
Pavel Töpfer Katedra software a výuky informatiky MFF UK MFF Malostranské nám., 4. patro, pracovna 404
[email protected] http://ksvi.mff.cuni.cz/~topfer
Pavel Töpfer, 2016
Programování 1 - 1
1
Cvičení NMIN101 Programování 1 - podle studijních skupin - možné přesuny v rámci volné kapacity (v SISu) - v počítačové učebně K11 (zřídit účet – u služby v K10) NMIN161 Praktikum z programování pro začátečníky 1 - volitelný předmět navíc, nenahrazuje cvičení NMIN101 - praktické procvičování ladění na počítači - přihlásit v SISu na základě doporučení cvičícího - otevřeny 3 skupiny (viz rozvrh v SISu) - výuka od 3. týdne semestru
Pavel Töpfer, 2016
Programování 1 - 1
2
Algoritmizace - metody řešení úloh na počítači – algoritmy, datové struktury, programovací techniky Správnost algoritmu - konečnost, parciální korektnost (správné výsledky, když výpočet skončí)
Efektivita algoritmu (složitost algoritmu) - časová (počet vykonaných operací) - prostorová (paměť potřebná na uložení dat) Programovací jazyk zápis algoritmu v programovacím jazyce = program - syntaxe (gramatika) - sémantika (význam) Programování jako „řemeslo“ - práce v integrovaném prostředí (editor + překladač + ladicí prostředky) - návrh testovacích dat, proces ladění programu Pavel Töpfer, 2016
Programování 1 - 1
3
Náplň zimního semestru Programovací jazyk: - deklarace (proměnné, konstanty, typy, inicializované proměnné) - jednoduché a strukturované datové typy (čísla, znaky, logické hodnoty, pole, znakové řetězce, záznamy) - jednoduché a strukturované příkazy (dosazovací příkaz, podmíněný příkaz, cyklus, složený příkaz) - textové soubory (včetně formátování výstupních dat) - procedury a funkce (lokalita identifikátorů, způsoby předávání parametrů, rekurze) - základní parametry překladače - návěští a příkazy skoku
Pavel Töpfer, 2016
Programování 1 - 1
4
Základní algoritmy a programovací techniky: - dělitelnost čísel, Eukleidův algoritmus - test prvočíselnosti, Eratosthenovo síto - Hornerovo schéma, poziční číselné soustavy - algoritmy vyhledávání v poli (sekvenční, binární, zarážka) - jednoduché třídění v poli - práce s maticemi (základní operace) - implementace zásobníku a fronty v poli - aritmetika s vyšší přesností („dlouhá čísla“ v poli) - aritmetické notace, převody a vyhodnocování - použití rekurze – backtracking, metoda „Rozděl a panuj“ - prohledávání do hloubky a do šířky - faktorové množiny (třídy ekvivalence)
Pavel Töpfer, 2016
Programování 1 - 1
5
Aktivní znalost integrovaného vývojového prostředí - editor, překlad, výpočet, trasování, sledování hodnot proměnných - ladění programů, testování správnosti (Borland Pascal nebo Free Pascal)
Pavel Töpfer, 2016
Programování 1 - 1
6
Řešte soustavu N lineárních rovnic o M neznámých. Spočítejte hodnotu Ludolfova čísla s přesností na 100 desetinných míst. Zašifrujte zadaný textový soubor zvolenou metodou.
Rozmístěte na šachovnici osm šachových dam tak, aby se žádné dvě navzájem neohrožovaly. Určete všechny způsoby, jimiž lze zaplatit zadanou částku pomocí známé sady platidel. Nalezněte v bludišti nejkratší cestu z daného místa ven.
Pavel Töpfer, 2016
Programování 1 - 1
7
P.Töpfer: Algoritmy a programovací techniky, Prometheus Praha 1995, 2. vydání 2007 učebnice přímo určená pro tento základní kurz programování, pokrývá většinu učiva algoritmů v obou semestrech (nevykládá syntaxi programovacího jazyka) P.Satrapa: Pascal pro zelenáče, Neocortex Praha 2000-2005 nebo jiná učebnice Pascalu J.Drózd, R.Kryl: Začínáme s programováním, GRADA Praha 1992 učebnice základů Pascalu a programování, vhodná pro začátečníky, nepokrývá celé učivo (nedostupná) P.Töpfer: Základy programování v úlohách, Scientia Praha 1997 učebnice základů programování, předváděny formou řešených příkladů, určena pro úplné začátečníky (první třetina ZS) P.Töpfer, D.Töpferová: Programování - Sbírka úloh, Fortuna 1998 sbírka jednoduchých i těžších úloh na procvičování P.Töpfer: Programování - Rekurze, Fortuna Praha 1998 výklad nejobtížnější partie v ZS - rekurze Pavel Töpfer, 2016
Programování 1 - 1
8
Vývoj programu 1. algoritmus programovací jazyk 2. program textový editor 3. zdrojový text programu překladač 4.a) syntaktická chyba zpět na opravu zdrojového textu 4.b) bez syntaktických chyb přeložený program spustit se vstupními daty 5.a) běhová chyba (příp. zacyklení výpočtu) ladicí prostředky, testování, zpět na opravu zdrojového textu 5.b) bez běhové chyby posouzení výsledků 6.a) podezřelé výsledky logická chyba ladicí prostředky, testování, zpět na opravu zdrojového textu 6.b) dobré výsledky ověřit správnost opakovaně pro různá testovací vstupní data Pavel Töpfer, 2016
Programování 1 - 1
9
Největší společný dělitel X, Y – dvě kladná celá čísla určit největší společný dělitel NSD(X,Y) Algoritmy: 1. NSD(X,Y) = největší z celých čísel od 1 do X (X < Y), které je dělitelem obou čísel X a Y – postupně zkoušet, nejlépe v pořadí od X k 1 do nalezení prvního takového společného dělitele 2. Určit prvočíselné rozklady čísel X a Y – jejich maximální společná část určuje NSD(X,Y) Např. 396 = 2.2.3.3.11, 324 = 2.2.3.3.3.3 NSD(396, 324) = 2.2.3.3 = 36
Pavel Töpfer, 2016
Programování 1 - 1
10
3. Eukleidův algoritmus Idea:
když X < Y když X > Y když X = Y
NSD(X,Y) = NSD(X,Y-X) NSD(X,Y) = NSD(X-Y,Y) NSD(X,Y) = X
Příklad: NSD(396,324) = NSD(72,324) = NSD(72,252) = NSD(72,180) = NSD(72,108) = NSD(72,36) = NSD(36,36) = 36 Algoritmus: dokud X Y dělej od většího z čísel X, Y odečti menší z čísel X, Y
Pavel Töpfer, 2016
Programování 1 - 1
11
Správnost Eukleidova algoritmu 1. Konečnost - na začátku výpočtu i stále v jeho průběhu je X>0, Y>0 - v každém kroku výpočtu se hodnota X+Y sníží alespoň o 1 nejpozději po X+Y krocích výpočet skončí, je tedy konečný 2. Parciální (částečná) správnost - pro X = Y zjevně platí NSD(X,Y) = X - ukážeme, že pro X > Y platí NSD(X,Y) = NSD(X-Y,Y): Nechť N=NSD(X,Y), tedy N dělí X a zároveň N dělí Y. Proto také N dělí X-Y a je tedy N společným dělitelem X-Y a Y. Pokud by neplatilo, že N=NSD(X-Y,Y), musí existovat A>1 tak, že N.A=NSD(X-Y,Y). Tedy N.A dělí X-Y i Y, takže N.A dělí i jejich součet, což je X. Jelikož N.A dělí Y a zároveň N.A dělí X, je N.A společným dělitelem X, Y, což je spor s tím, že N=NSD(X,Y). Proto N=NSD(X-Y,Y). Pavel Töpfer, 2016
Programování 1 - 1
12
Efektivita algoritmu (složitost algoritmu) - časová počet vykonaných operací rychlost výpočtu programu - prostorová (paměťová) velikost datových struktur využívaných algoritmem paměť potřebná na uložení dat při výpočtu programu Kritéria pro hodnocení kvality algoritmu a programu (příp. praktické použitelnosti programu). Obě kritéria mohou mířit proti sobě (nelze najednou optimalizovat paměť i čas), musíme zvolit, čemu dáme přednost (dnes obvykle čas).
Funkce vyjadřující počet vykonaných operací (resp. velikost potřebné paměti) v závislosti na velikosti vstupních dat. Jako velikost vstupních dat obvykle stačí uvažovat např. počet zpracovaných čísel, nikoliv konkrétní hodnoty (jedná-li se o hodnoty „standardní“ velikosti). Obecně by se musela uvažovat velikost vstupních dat v bitech. Pavel Töpfer, 2016
Programování 1 - 1
13
Funkce časové a prostorové složitosti jsou většinou rostoucí (nad většími daty bývá výpočet delší). Přesné vyjádření funkce časové složitosti (např. 3.N 2 + 2.N - 4) je jednak obtížné, jednak většinou zbytečné. Podstatná je řádová rychlost růstu této funkce pro rostoucí N. Zanedbáme pomaleji rostoucí členy a konstanty asymptotická časová složitost O(N 2). Symbol „velké O“ f = O(g) c n0 n > n0 : f(n) < c.g(n) tzn. funkce f se dá shora odhadnout funkcí g (až na multiplikativní konstantu a pro dostatečně velká n) Opačný odhad (zdola): f = (g) Přesný odhad: f = (g) f = O(g) f = (g)
Pavel Töpfer, 2016
Programování 1 - 1
14
Poznámka: Funkce 3.N 2 + 2.N - 4 patří nejen do třídy O(N 2), ale podle definice také třeba do třídy O(N 5). Odhad složitosti O(N 5) je zde sice správný, ale zbytečně hrubý a nepřesný, vždy se snažíme o co nejlepší (nejnižší) odhad. Proto je pro nás mnohem cennější (ale mnohdy také obtížnější) odvodit odhad asymptotické časové složitosti algoritmu (N 2) než jenom O(N 2).
Pavel Töpfer, 2016
Programování 1 - 1
15
Asymptotická časová složitost Typické asymptotické časové složitosti algoritmů: O(1), O(log N), O(N), O(N.log N), O(N 2), O(N 3), …, O(2N) Hledáme algoritmus s co nejmenší asymptotickou časovou složitostí, tedy co nejrychlejší pro velká N. Pro malá N může být třeba i horší než nějaký jiný algoritmus, ale pro malá N to nevadí, doba výpočtu je vždy dostatečně krátká. - polynomiální – obvykle zvládnutelné i pro velká N - exponenciální – pro větší N časově nezvládnutelné, použitelné jen v případě, že vstupní data budou vždy malá
Pavel Töpfer, 2016
Programování 1 - 1
16
Exponenciální časová složitost Příklad: Ke zpracování vstupních dat velikosti N algoritmus vykoná 2N operací. Rychlost počítače: 109 operací za sekundu (řádově GHz – dnešní PC).
N 20 30 40 50 60 70 80 90 100
doba výpočtu 1 ms 1s 17 min 11 dní 31 let 3.104 let 3.107 let 3.1010 let 3.1013 let
Pro vyšší N (cca 50) je algoritmus prakticky nepoužitelný. Nepomůže nám ani rychlejší počítač! Pavel Töpfer, 2016
Programování 1 - 1
17
Složitost algoritmu v různých případech Pro každá vstupní data velikosti N nemusí trvat výpočet stejně dlouho, rozdíl může být jen v konstantě, nebo i v asymptotické složitosti Časová složitost algoritmu v nejhorším případě = maximální počet operací vykonaných algoritmem pro nějaká data velikosti N nejčastěji používaná pro hodnocení algoritmů Časová složitost algoritmu v nejlepším případě = minimální počet operací vykonaných algoritmem pro nějaká data velikosti N prakticky se nepoužívá
Časová složitost algoritmu v průměrném případě = průměrný (očekávaný) počet operací vykonaných algoritmem pro data velikosti N (průměr pro všechna možná vstupní data velikosti N) dobře charakterizuje kvalitu algoritmu, ale je obtížné odvodit ji Pavel Töpfer, 2016
Programování 1 - 1
18
Složitost problému - složitost nejlepšího algoritmu (z hlediska časové složitosti), kterým lze řešit daný problém Nelze odvodit ze složitosti nějakého konkrétního algoritmu ani třeba všech běžně známých algoritmů, charakterizuje problém obecně (jaký nejlepší algoritmus řešící problém může v principu existovat) odvození je obtížné, pro řadu problémů neznáme. Příklady: 1. Nalézt maximum z daných N čísel časová složitost problému O(N) - existuje algoritmus s časovou složitostí O(N) … triviální - nemůže existovat algoritmus s lepší časovou složitostí … maximem může být kterékoliv z N čísel, takže na každé se musí algoritmus podívat 2. Seřadit daných N čísel podle velikosti (problém třídění) časová složitost problému O(N. log N) - existuje algoritmus s časovou složitostí O(N. log N) … např. heapsort - nemůže existovat algoritmus s lepší časovou složitostí … oboje si ukážeme později Pavel Töpfer, 2016
Programování 1 - 1
19