Dragi takmičari,
U prilogu se nalazi 2 verzija reenja 2. zadataka sa 2. kruga kvalifikacija - Trivijalan broj, odnosno prva optimizacija:
- Algoritamsko reenje 2. verzije koja daje tačne rezultate za sve test primere, ali je vremenski optimizovana (FlowGorithm).
- Odgovarajući programski kod u Pascal-u (.pas).
- Slika punih povratnih informacija sa sistema, nakon postavljanja programskog koda - reenje se boduje sa 100 bodova (.png).
Kao to moete da primetite razmiljali smo na sledeći način:
- Posebnu panju obratite na proste brojeve. Primetićete da prosti brojevi imaju najmanje količnike koji su uvek (1+x)/x, odnosno 1 + 1/x.
- Takođe, primetićete da, naročito za velike brojeve x, da je glavni deo zadatka da pronađemo prvi prost broj koji je manji od x.
Iz ovoga izvlaćimo sledeće zaključke:
- Izgleda da uopte nije potrebno da izraćunavamo sumu svih delilaca, a jo manje da traimo (upoređujemo) čija je suma najmanja.
- Umesto toga potrebno je da pronađemo prvi (najveći) prost koji je manji od X i to je sve.
- Da bi pronali prvi (najveći) prost broj koji je manji od X bilo bi dobro (i zbog vremenske optimizacije) da brojač te petlje krene sa provreom od broja X (da li je prost), pa ako nije da proveri prvi sledeći manji (X=X-1) i tako redom sve dok ne naiđe na prvi prost broj (ili dođe do broja 2).
- Za ovakvu cikličnu stukturu (petlju) mnogo je bolje i efikasnije da koristimo ciklus sa uslovom (While) umesto brojačkog ciklusa (For), s tim to obavezno moramo samo da vodimo računa o uslovu petlje, odnosno brojaču, kako ne bi napravili večnu (mrtvu) petlju.
- Takođe, dodatno smo malo ubrzali algoritam, tako to smo zaključili da parni brojevi (veći od 2) nisu prosti, pa je bolje da ispitujemo samo neparne. Dakle, prvo proverimo da li je broj X paran, pa ako jeste odmah mu smanjimo vrednost za 1 (odnosno uzimamo prvi sledeći manji), pa tek onda počinjemo petlju.
- Radi lakeg praćenja i provere, uveli smo i logičku promenljivu Prost, koju inicijalno postavljamo na True, a ako naiđemo na prvi delilac postavljamo na False.
- Promenljiva P će imati vrednost prvog najvećeg pronađenog prostog broja, manjeg (ne većeg) od X, te na početku postavljamo vrednost 0 ovoj promenljivoj (umesto nule, mogli smo i 1, radilo bi ispravno).
- Dodatno smo ubrzali cikličnu strukturu sa uslovom (While), jer na ona to omogućava, tako to smo za uslov da se izvrava stavili sve dok ne pronađemo P (odnosno P=0) i za svaki slučaj dok X ne smanjimo toliko da dođe do 2.
- Dodatno smo ubrzali cikličnu strukturu sa uslovom (While), jer na ona to omogućava, tako to smo brojač X koji učestvuje u uslovu petlje u svakom prolasku kroz petlju smanjili za 2 (a ne za 1 kao kod for), odnosno ispitivaćemo samo neparne brojeve (svaki drugi).
- Ovaj programski kod nije maksimalno vremenski optimizovan, ali jeste sasvim dovoljno da prođe sve test primere i osvoji 100 bodova na kvalifikacijama.
- Svi test primeri se izvravaju za manje od 2 sekunde, to moete proveriti i kroz FlowGortithm i kroz programski kod u razvojnom okruenju, ali na samom sistemu.
- Ipak, obratite panju na test primere 10 i 11. Za izvravanja ova dva test primera bilo je potrebno 0,63 i 0,48 sekundi (jer se ispituju brojevi veći od milion). Recimo da nismo ispitivali samo neparne brojeve, već sve (duplo sporije) i/ili da nismo u uslovu petlje stavili i (P=0) ova dva test primera bi bila dua od 2 sekunde, pa ne bi bili bodovani.
- Za jo bolju, siigurniju i bru vremensku optimizaciju, odnosno bre izvravanje programskog koda, potrebno je da se upoznamo sa matematičkim osnovama teorije brojeva i deljivosti celih brojeva, kao i algoritamskim metodama za primenu tih matematičkih osnova. O tome, neto detaljnije moete pronaći na:
https://petljamedia.blob.core.windows.net/root/Media/Default/Lecture/Matematicki%20Algoritmi%201/Matematicki%20algoritmi%20I%20-%20Deljivost.pdf
Ipak, nemojte previe uriti sa čitanjem ovih materijala, naročito ukoliko jo uvek niste dobro proučili ovu prvu vremensku optimizaciju, koja osvaja maksimalan broj bodova na kvalifikacijama. - Povratne informacije o rezultatima programskog koda moete proveriti na: https://arena.petlja.org/Competitions/Competition/171
Dodatni materijali za nastavak poboljanja vremnske optimizacije:
Pozdrav,
Dragan Ilić
Dragan Ilić
----- Original Message -----
From: Dragan Ilic
Sent: Sunday, January 28, 2018 12:11 PM
Subject: Takmicenje iz programiranja 2017 - Kvalifikacije - 2. krug - Zadatak 2 - Trivijalan broj - Resenje - Verzija 1 - Nije optimizovano
Dragi takmičari,
U prilogu se nalazi 1 verzija reenja 2. zadataka sa 2. kruga kvalifikacija - Trivijalan broj:
- Ceo tekst zadatka (png slika).
- Algoritamsko reenje 1. verzije koja daje tačne rezultate za sve test primere, ali nije vremenski optimizovana (FlowGorithm).
- Odgovarajući programski kod u Pascal-u (.pas).
- Slika punih povratnih informacija sa sistema, nakon postavljanja programskog koda - reenje se boduje sa 30 bodova (.png).
Većina takmičara je dola do sličnih reenja. Ovo je objedinjeno reenje svih verzija reenja naih takmičara. Takođe, ovo bi bilo najjednostavnije reenje zadatka koje daje traene tačne rezultate za sve unapred pripremljene test primere. Međutim, ovo reenje ne osvaja maksimalni broj bodova na takmičenju, jer ne ispunjava sve navedene uslove u takmičarskom zadatku, tačnije ne ispunjava vremenska ograničenja.
Ako paljivo pogledate povratne informacije sa sistema, primetiće sledeće:
- Reenje zadatka vraća statuse OK za prva 4 test primera, s tim to se prvi (iz teksta zadatka) ne boduje (boduje se 10 test primera od rb 2 do 11 po 10 bodova).
- Vreme izvravanja programskog koda za prva 4 test primera je po oko 0,02 sekunde, to je sasvim pristojno. Međutim, to je zato to se radi o relativno malim brojevima (manjim od 1000).
- Za sve ostale test primere statusi su TLE, to znači da je dolo do vremenskog prekoračenja (Time Limit Excided), odnosno da je za svaki test primer bilo potrebno vie od po 2 sekunde za izvravanje.
- Do vremenskog prekoračenja dolazi zbog velikih brojeva (preko hiljadu, tačnije nekoliko desetina i stotina hiljada), jer imamo 2 ugnjedene petlje obe po nekoliko hiljada (zajedno preko milion prolazaka kroz petlje).
- Program u odnosu na algoritam smo malo ubrzali (prva petlja ne ide do N nego do N/2) to je duplo smanjilo vreme izvravanja, ali očigledno ne dovoljno.
- Kako bi se sami uverili koliko je izvravanje ovakvog algoritamskog reenja sporo za velike brojeve, moete da iskoristite algoritam iz priloga u FlowGoritthmu i da unesete najpre male brojeve, zatim oko hiljadu, pa oko 10 hiljada, pa 100 hiljada. Zatim slično uradite sa programskim kodom iz razvojnog okruenja.
- Vremenska optimizacija programskog koda je moda najtea, jer zahteva puno rada, vebi, testiranja, proučavanja, analize, kao i dobro poznavanje matematike i algoritamskih metoda. Iskoristićemo ovo takmičenje da postepeno počnemo da učimo i vremensku optimizaciju, posebno kroz ovaj zadatak/primer i veoma vaan primer za proste brojeve.
- Za početak, jo jednom pročitajte uputstva koja sam vam poslao pre nekoliko dana, a naročito poslednje korake.
- Takođe, nije loe da jo jednom pregledate osnovne informacije o prostim brojevima i na vikipediji:
https://sr.wikipedia.org/sr-el/%D0%9F%D1%80%D0%BE%D1%81%D1%82_%D0%B1%D1%80%D0%BE%D1%98 - U narednim mejlovima poslaću vam prva uputstva za vremensku optimizaciju ovog zadatka, postepeno korak po korak.
Pozdrav,
Dragan Ilić
Dragan Ilić
----- Original Message -----
From: Dragan Ilic
Sent: Thursday, January 25, 2018 10:47 PM
Subject: Takmicenje iz programiranja 2017 - Kvalifikacije - 2. krug - Zadatak 2 - Trivijalan broj - Algoritamsko resenje (nije optimizovano)
Dragi takmičari,
U prilogu se nalazi algoritamsko reenje 2. zadataka, ali potpuno neoptimizovano, ipak, najjednostavnije za razumevanje ta se zapravo trai u zadatku.
Organizatori takmičenja u ovom zadatku trae vremensku optimizaciju programskog koda, a za tako neto je potrebno iskustvo, veba, vereme i poznavanje posebnih alogoritamskih metoda, koje ćemo postepeno početi da učimo od ovog zadatka.
Programski kod u prilogu daje tačne rezultate za sve test primere, ali veoma sporo, tako da će osovojiti bodove samo za prva 3 test primera, odnosno 30 bodova, to se moete i sami uveriti do 28.01, tako te ćete postaviti programski kod iz priloga na:
Kako onda da naučimo vremenskiu optimizaciju?
Postepeno i polako. Za sam početak koristićemo recimo Excel kao pomoć da bolje uočimo neke nove sličnosti i meusobnu zavisnost traenih brojeva u zadatku.
U prilogu se nalazi i Excel fajl kao pomoć pri reanju drugog zadatka Trivijalan broj:
- Prikazani su podaci za prvih 1050 (počev od 2) brojeva u 3 kolone: X - prirodan broj (Ai), S - zbir svih jnegovih pozitivnih delilaca i TB - trivijalnost broja X, odnosno količnih S / X (prikaz podataka u ovoj koloni je na 3 decimale, ali moete namestiti na vie 5 ili 6 da bi bolje uočili razlike).
- U samom zadatku X moe biti do 5 miliona, a ovde smo prikazali samo do 1050, ali je princip isti.
- Ovaj zadatak moemo da reimo bez upotrebe nizova i relativno jednostavno, ako ne vodimo računa o vremenskoj optimizaciji, tako to ćemo za svaki broj x pronaći i sabrati sve njegove delioce, a zatim podeliti zbir sa samim brojem i taj količnik proveriti da li je manji od do tada najmanjeg (početni najmanji je 1,5 za broj 2).
- Sve promenljive su celobrojne (LongInt) osim promenljive za količnik i najmanji količnik koje su Real (ne moraju biti double).
- Tek kada tako reite zadatak, testirajte za nekoliko test primera i proverite sa podacima u ovoj tabelu u Excel-u (u prilogu).
- Reenje (bez vremenske optimizacije) će verovatno proći sve test primere, međutim zbog vremenskog ograničenja, sigrno sporo, to znači da će bodove imati samo za nekoliko jednostavnih test primera (sa ne mnogo velikim brojevima).
Tek kada ovako reite zadatak, ako imate vremena, moete da počnete da razmiljate o vremenskoj optimizaciji postepeno po sledećim koracima:
- Obratite panju da su svi količnici u opsegu između 1 i 4, tačnije 3,5.
- Kako se uvek kreće od broja 2, to znači da treba traiti najmanji količnik u opsegu između 1 i 1,5.
- Obratite panju na cikličnu strukuturu za izračunavanje zbira delilaca ne mora da kreće od 1 i da ide do broja x, jer svaka suma u stratu ima početni zbir 1+x, jer je svaki broj deljiv sa 1 i samim sobom. Dakle brojač petlje ne ide od 1 do X, već od 2 do x-1, mada to i nije neka velika vremenska uteda, ali u ovom slučaju nije ni zanemarljiva, jer za svaki broj x ponavljamo ovu unutranju petlju.
- Takođe obratite panju da prilikom izračunavanja zbira delilaca nema potrebe da ispitujemo da li je broj x deljiv sa brojevima koji su veći od x/2, jer sigurno nije. To znači da brojač ciklusa moe da ide od 2 do x / 2, odnosno x div 2, to već donosi dvostruku utedu u brzini rada.
- Zatim pređite na Excel fajl i posmatrajte količnije parnih i neparnih brojeva. ta primećujete?
- Moete i da sortirate podatke po TB u rastućem redosledu, pa ponovo pregledajte sve podatke.
- Posebnu panju obratite na proste brojeve. Primetićete da prosti brojevi imaju najmanje količnike koji su uvek (1+x)/x, odnosno 1 + 1/x.
- Takođe, primetićete da, naročito za velike brojeve x, da je glavni deo zadatka da pronađemo prvi prost broj koji je manji od x.
- S obzirim da je trivijalnost broja 2 (kolčinik) 1.5, a broja 3 1,33, sledećeg neparnog i prostog broja 5 1,2 i 7 1,143, a već broja 13 1,077, teko da ćemo naići na neki broj veći od 1000 koji nije prost a čija je trivijanost manja od 1,1, tačnije od 1,077. Pa čak i da postoji, u prvih 1000 brojeva najveći prost broj je 997 čija je trivijalnost 1,001. Dakle, i bez previe matematičkih alata (teorema, dokaza), ali uključujući logiku, testiranje i matemtićko poznavanje prostih brojeva, količnika i uočvanja pravila (rasta ili opadanja vrednosti) moemo prilčno da ubrzamo agloritamsko reenje.
Pozdrav,
Dragan Ilić
Нема коментара:
Постави коментар