1 / 51

3. tekmovanje IJS v znanju računalništva

3. tekmovanje IJS v znanju računalništva. Naloge in rešitve Janez Brank 29. marca 2008. 1.1 GrbaveBesede. Beseda je grbava , če se v njej vsaj dvakrat pojavi mala črka neposredno za veliko Primer: DomNaKrimu, WriteLn Ne pa: naKrimu, Write, NaOH

mia-paul
Download Presentation

3. tekmovanje IJS v znanju računalništva

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 3. tekmovanje IJS v znanju računalništva Naloge in rešitveJanez Brank29. marca 2008

  2. 1.1 GrbaveBesede • Beseda je grbava, če se v njej vsaj dvakrat pojavi mala črka neposredno za veliko • Primer: DomNaKrimu, WriteLn • Ne pa: naKrimu, Write, NaOH • Napiši program, ki prebere besedilo in izpiše tiste besede v njem, ki so grbave.

  3. 1.1 GrbaveBesede • Berimo besedilo znak po znak • V neki spremenljivki štejmo, koliko grb ima trenutna beseda • Če je prejšnji znak velika črka, trenutni znak pa mala, povečamo število grb • Če je prejšnji znak črka, trenutni znak pa presledek (ali konec vrstice), smo na koncu besede • Če ima vsaj dve grbi, jo izpišemo

  4. 1.2 Predavalnice • Dani so časi začetka in konca predavanj • Zanima nas največje število predavanj, ki potekajo hkrati • (Da vemo, koliko predavalnic bomo potrebovali) • Lažja različica: časi so podani v urah in minutah • Težja: časi so poljubna realna števila

  5. 1.2 Predavalnice • Lažja različica: časi v urah in minutah • In vse se dogaja znotraj enega dneva • Dan ima le 24 · 60 = 1440 minut • Imejmo tabelo 1440 elementov; v njej za vsako minuto piše, koliko predavanj je takrat v teku • Na začetku postavimo vsa ta števila na 0 • Za vsako predavanje gremo od začetnega do končnega časa in povečujemo števila v tabeli za 1 • Na koncu poiščemo največje število v tabeli

  6. 1.2 Predavalnice • Težja različica: časi so poljubna realna števila • Do sprememb v številu hkratnih predavanj lahko pride le takrat, ko se kakšno predavanje začne ali konča • Uredimo čase začetka in konca predavanj • Pregledujmo te čase po vrsti: • Ko se neko predavanje začne, povečamo števec za 1 • Ko se neko predavanje konča, zmanjšamo števec za 1 • Sproti si zapomnimo, katera je bila največja dosežena vrednost števca • Če se v nekem trenutku kakšno predavanje začne, kakšno pa konča, upoštevajmo najprej tisto, ki se konča [na to moramo paziti že pri urejanju časov]

  7. 1.3 Darila • Imamo n oseb • Vsak je dal vsem drugim darila(različnih vrednosti) • Kdo je imel največ dobička? • Torej največjo razliko med skupno vrednostjo prejetih in podarjenih daril

  8. 1.3 Darila • Rešitev: • Zunanja zanka gre po vseh osebah • Z notranjo zanko gremo še enkrat po vseh osebah • Prištevamo vrednosti prejetih daril, odštevamo vrednosti podarjenih daril • Rezultat je dobiček te osebe • Če je to največji doslej znani dobiček, si ga zapomnimo (in tudi številko te osebe).

  9. 1.4 Elektronska ključavnica • Napiši program za krmiljenje elektronske ključavnice: • Na njej so tipke 0..9 in “prekliči” • Ko uporabnik natipka pravo geslo, se naj ključavnica odklene • Če se uporabnik zatipka, vse nadaljnje pritiske na tipke ignoriramo, dokler ne pritisne gumba “prekliči”

  10. 1.4 Elektronska ključavnica • Program teče v neskončni zanki: • V neki spremenljivki g si zapomnimo doslej natipkani del gesla • Še ena spremenljivka z pa pove, če se je uporabnik že zatipkal • Ob pritisku na “prekliči” obe spremenljivki resetiramo • Če se je uporabnik že zatipkal, pritiske na števke 0..9 ignoriramo • Sicer preverimo, če je bila pritisnjena prava tipka (naslednja števka gesla) • Če ni bila, se je zatipkal (postavimo z na true) • Sicer dodamo novo števko na konec g • Če je g zdaj enak geslu, odklenemo ključavnico in g postavimo spet na prazen niz.

  11. 1.5 Kdo je izdal skrivnost? • Dan je seznam telefonskih pogovorov • Za vsak pogovor je znano, katera dva človeka sta se pogovarjala • Pogovori so urejeni po času • Zanima nas, ali je lahko oseba a prek enega ali več klicev posredovala neko informacijo osebi b. • Zanima nas tudi dolžina najkrajšega takega zaporedja klicev.

  12. 1.5 Kdo je izdal skrivnost? • Pri tej nalogi je ljudi le 10000 (štirimestne telefonske številke) • Za vsakega v neki tabeli hranimo podatek o tem, kako dolgo je najkrajše znano zaporedje klicev na poti od a do njega (in kdo je njegov predhodnik na tej poti) • Na začetku je znana le pot do a (dolžine 0) • Klice pregledujemo po času • Pri vsakem klicu (x, y): • Če je znana pot dolžine d od a do x, imamo zdaj tudi pot od a do y dolžine d + 1; če tako kratke poti do y doslej nismo poznali, si zapomnimo to. • Možno je tudi obratno (pot od a do y + korak od y do x = mogoče nova najkrajša pot od a do x)

  13. 2.1 Roboti • Imamo več seznamov • Elementi vsakega seznama so točke (x, y),x, y {1, …, n} • Zanima nas, ali je kakšna točka prisotna na vseh seznamih.

  14. 2.1 Roboti • Rešitev s tabelo: • Imejmo tabelon×n elementov • Na začetku postavimo vse na 0 • Za vsak seznam: • Za vsako točko (x, y) na seznamu: • Povečajmo v tabeli T[x, y] za 1 • Na koncu torej za vsako točko vemo, v koliko seznamih je prisotna • Slabost: O(n2) pomnilnika • Preveč, če je n velik • Boljša različica: razpršena tabela (hash table) • Poraba pomnilnika je sorazmerna s številom točk v seznamih

  15. 2.1 Roboti • Rešitev z razlikami seznamov: • Začnimo s prvim seznamom (recimo mu S) • Za vsakega od ostalih seznamov (recimo S'): • Pobrišimo iz S vse elemente, ki jih ni v S' (*) • Na koncu ostanejo v S le tisti elementi, ki so prisotni v vseh seznamih • Kako izvesti korak (*)? • Preprosta rešitev: dve gnezdeni zanki • Bolj učinkovito: sezname uredimo po koordinatah in jih zlivamo (= premikamo se z dvema števcema hkrati po obeh seznamih)

  16. 2.2 rsync • Imamo seznam zapisov oblike ime, datum • Naš namen je, da bi imeli na koncu za vsako ime le zapis z najnovejšim datumom. • To počnemo z naslednjim postopkom: • uredi seznam padajoče po datumu • uredi seznam naraščajoče po imenu • za vsak zapis poglej, če ima isto ime kot prejšnji; če ga ima, ga pobriši. • Ureja se takole: • for i := 0 to n – 2 do for j := i + 1 to n – 1 do if T[i].datum <= T[j].datum then swap(T[i], T[j]);for i := 0 to n – 2 do for j := i + 1 to n – 1 do if T[i].ime >= T[j].ime then swap(T[i], T[j]); • Ali ta postopek deluje pravilno? • Če ne, ga moramo popraviti

  17. 2.2 rsync • Postopek ne deluje pravilno • Pri urejanju po imenu pridejo skupaj zapisi za isto ime • Na koncu obdržimo le prvega od njih – ta bi moral torej biti najnovejši • Po urejanju po datumu je bil res najnovejši zapis za vsako ime pred vsemi ostalimi zapisi za tisto ime. • Toda ali je urejanje po imenu to lastnost ohranilo? • Žal ne: • Ker uporabljamo “>=” namesto “>”, včasih zamenjamo dva zapisa z istim imenom • Zapis se lahko ob zamenjavi premakne daleč naprej, tudi mimo takih, ki imajo isto ime, a zgodnejši datum • Rešitev: T[i] in T[j] ne zamenjamo, pač pa T[j] vrinemo pred T[i], tako da dobimo T[j] T[i] T[i+1] … T[j-1] T[j+1] …

  18. 2.3 Usklajevanje ur • Implementirati moramo protokol za sinhronizacijo ure na odjemalcu • (1) strežnik pošlje svoj trenutni čas t1 odjemalcu • (2) odjemalec si zapomni čas prejema, t2; nato ob času t3 pošlje strežniku odgovor • (3) strežnik si zapomni čas prejema, t4, in ga pošlje odjemalcu • Zdaj lahko odjemalec izračuna razliko med svojo in strežnikovo uro in jo pri sebi popravi.

  19. 2.3 Usklajevanje ur • Naloga zahteva, da definiramo vsebino sporočila in napišemo tri podprograme: • Sporočilo naj vsebuje čase t1, t2, t3, t4 in zaporedno številko sporočila (1, 2 ali 3) • SinhronizirajUro mora začeti celoten postopek • To pomeni, da odjemalcu pošlje (1; t1) • SprejemNaStrežniku mora odreagirati na 2: • Takrat pošlje odjemalcu (3; t1, t2, t3, t4) • SprejemNaOdjemalcu mora odreagirati na 1 in 3: • Ko prejme 1, pošlje strežniku (2; t1, t2, t3) • Ko prejme 3, izračuna razliko in popravi uro.

  20. 2.4 Društvo ljubiteljev ničel • Dana je tabela n elementov, vsi so 16-bitna cela števila (0..65535) • Radi bi jih vse xorali z nekim 16-bitnim številom c, tako da bi bilo po tem v tabeli čim manj prižganih bitov • a := a xor c pomeni, da če je nek bit v c prižgan, bomo tisti bit v a obrnili (iz 0 v 1 ali iz 1 v 0), ostale bite a-ja pa pustimo pri miru • Kateri c naj izberemo?

  21. 2.4 Društvo ljubiteljev ničel • Lepo pri operaciji xor je, da jo lahko računamo po bitih • To, kar se dogaja na nekem bitu, je neodvisno od tega, kar se dogaja na drugih bitih • Za vsak bit poglejmo, koliko števil v tabeli ima ta bit prižgan, koliko pa ugasnjen • Če je več prižganih kot ugasnjenih, postavimo ta bit v c na 1, ta se bodo prižgani spremenili v ugasnjene in obratno • Sicer pa pustimo ta bit v c na 0 • Če je n res velik, se splača za vsako možno vrednost od 0 do 65535 najprej prešteti, kolikokrat se pojavlja v naši tabeli

  22. 2.5 Cik cak • Naloga: • dan je opiscikcakaste črte iz znakov/ in \, npr.: \//\//\\/\\/// • Radi bi jo narisali prek več vrstic,pod črto o-je, nad črto pike

  23. 2.5 Cik cak • Rešitev: • Recimo, da se črta začne na višini y = 0. • V prvem prehodu po nizu poiščemo najvišjo in najnižjo točko. • Nato za vsako vrstico naredimo še en prehod čez niz; • gledamo, na kakšni višini je črta; • če je črta nad našo vrstico, napišemo o; • če je pod njo, napišemo piko; • sicer napišemo trenutni znak / ali \.

  24. 3.1 PINi • Pri tej nalogi so PINi zaporedja n števk • Iz starega PINa dobimo novega takole: • seštejemo števke • pripišemo zadnjo števko vsote • prvo števko pobrišemo • Primer: 1234  2340  3409  4096  … • Vprašanje: po koliko korakih se začnejo ponavljati (za dani začetni PIN)? • Koliko ločenih ciklov obstaja? • Koliko PINov je na krajšem ciklu od danega PINa?

  25. 3.1 PINi • Pri tej nalogi je n ≤ 6, zato je možnih največ 106 = milijon PINov • Imejmo neko tabelo 106 elementov, v kateri za vsak PIN piše, ali smo že naleteli nanj in na kako dolgem ciklu je • x := ZacetniPIN; d := 0;while not ZeVideno[x]:ZeVideno[x] := true;x := Naslednji(x); d := d + 1; • Zdaj vemo, kako dolg je cikel; nato naredimo še en obhod po njem in v tabelo vpisujemo, da so ti elementi na ciklu dolžine d. • Potem vzamemo kakšen še ne obiskan PIN in postopek ponovimo pri njem.  Dobimo nov cikel, ločen od prejšnjega • itd., dokler ne obiščemo vseh PINov.

  26. 3.2 Berberi • Na karirasti mreži sooznačene poti, po katerihso se selili Berberi • Občasno se poti razvejijo • Na prvi razvejitvi so seločili Y-ovi pristaši od M-jevih • Na vsaki razvejitvi nastanenaselje • Tudi na koncu poti nastane naselje • Koliko naselij ima zdaj Y, koliko pa M?

  27. 3.2 Berberi • Selitvam sledimo sistematično,od začetka (na levem robu) • Pri razvejitvi gremo najprej po enem in nato po drugem možnem nadaljevanju • Pri vsakem polju si označimo, iz katerega soseda smo vanj prišli • Ko se vrnemo iz polja, si označimo, da je že pregledano • Posebej si zapomnimo, kje je prva razvejitev in ali smo zdaj na sledi Y-ovih ali M-jevih pristašev • Ko smo v razvejitvi ali v polju brez naslednikov, povečamo števec naselij

  28. 3.3 Piskrc špagetov • Imamo nškatel špagetov, v i-ti škatli je mi špagetov dolžine di • Špagete lahko razpolavljamo • Iz špageta dolžine 2k nastaneta 2 špageta dolžine k • Iz špageta dolžine 2k + 1 nastane en špaget dolžine k in en špaget dolžine k + 1 • Razpoloviti smemo b špagetov • Radi bi, da bi bil na koncu najdaljši špaget čim krajši.

  29. 3.3 Piskrc špagetov • Pametno je v vsakem koraku razpoloviti najdaljši špaget • Če imamo več enako dolgih najdaljših špagetov, moramo razpoloviti vse (celo škatlo) • Vhodni seznam škatel je že urejen po dolžini špagetov (tako zagotavlja besedilo naloge) • Ko razlomimo vse špagete v neki škatli, nastaneta ena ali dve škatli s krajšimi špageti • Te nove škatle odlagamo na konec nekega novega seznama (ki je tako tudi urejen) • Na vsakem koraku prelomimo tisto škatlo, v kateri so najdaljši špageti (lahko je iz originalnega ali pa iz novega seznama)

  30. 3.4 Redki nizi • Imamo niz znakovs[1..n] • Najprej vse znake postavimo na c • Nato čez znake s[z1..(z1 + d1 – 1)] vpišemo znake niza t1[1..d1] • Potem naredimo enako za t2, …, tk(vsak ti ima svojo dolžino di in začetni položaj zi) • Primer: n = 20, c = xxxxxxxxxxxxxxxxxxxxxt1 = abcfg, z1 = 10  xxxxxxxxxabcfgxxxxxxt2 = fghxjx, z2 = 7  xxxxxxfghxjxfgxxxxxxt3 = xfg, z3 = 17  xxxxxxfghxjxfgxxxfgx = s • V tako dobljenem nizu s iščemo vse pojavitve niza p • s je dolg do 109 znakov, vsi ti-ji skupaj največ 106 znakov, p največ 100 znakov

  31. 3.4 Redki nizi • s je dolg 109 znakov, vsi ti-ji skupaj le 106 večino nizas še vedno pokrivajo znaki c • s razdelimo na kose, sestavljene iz c-jev, inkose, ki jih pokrivajo ti-ji • Pri prejšnjem primeru: xxxxxxfghxjxfgxxxfgx • ti-ji se lahko med seboj prekrivajo • uredimo jih po začetnem indeksu • če se naslednji t začne prej, kot se prejšnji konča, sta del istega kosa, itd. • vsakega od kosov, nastalih iz ti-jev, predstavimo z nizom;za kose iz samih c-jev pa si zapomnimo le dolžino • pojavitev p-ja znotraj kosov oblike ccc..cc ni težko prešteti • tiste pojavitve, ki ležijo (vsaj delno) v kakšnem kosu,nastalem iz ti-jev, pa poiščemo na staromoden način (primerjamo znakep-ja in s-ja enega po enega)

  32. 3.5 Obračanje bitov • Imamo tabelow×h polj, vsako polje je lahko črno ali belo • daljša stranica je ≤ 50, krajša je ≤ 21 • Dovoljena operacija: izberemo neko vrstico ali stolpec in spremenimo barvo vseh polj v njej (črna postanejo bela in obratno) • S takimi operacijami bi radi čim bolj zmanjšali število črnih polj

  33. 3.5 Obračanje bitov • Nekaj opažanj: • Vrstni red operacij ni pomemben • Nobene vrstice ali stolpca ni smiselno obrniti več kot enkrat • Torej ostane le še vprašanje, katere vrstice in stolpce bi obrnili • V zunanji zanki preizkusimo vse možne izbore stolpcev: • Za vsak izbor stolpcev si ogledamo mrežo, kakršna nastane po obračanju teh stolpcev. • Obrnemo vse tiste vrstice, ki imajo več črnih polj kot belih. • Za učinkovito implementacijo: • Izbrano množico stolpcev predstavimo kot w-bitno celo število. • Ravno tako tudi vsako vrstico. • Za vsako w-bitno celo število potabeliramo število prižganih bitov v njem. • Če je w > h, tabelo diagonalno prevrnemo.

  34. Greed, for want of a better word, is good. Greed is right, greed works. Gordon Gekko, Wall Street (1987) Kino (off-line naloga)

  35. Opis naloge • To je “off-line naloga”: • opis naloge in vhodne podatke smo objavili pred nekaj meseci • tekmovalci so lahko oddajali rešitve našemu ocenjevalnemu strežniku do vključno včeraj • Naloga: sestavi celoletni spored filmov v kinematografu, tako da bo prodanih čim več vstopnic • Dani so podatki: • seznam prebivalcev našega kraja;za vsakega prebivalca poznamo: • katere žanre filmov rad gleda • ob kateri uri je najraje v kinu • seznam filmov, ki jih lahko predvajamo;za vsak film poznamo: • katerim žanrom pripada • popularnost filma • trajanje filma v minutah • število sedežev v kino dvorani

  36. Ocenjevanje • Ocenjevali smo s programom, ki je simuliral odločitve gledalcev: • Za vsako predstavo v celoletnem sporedu: • Za vsakega gledalca: • Oceni verjetnost, da bi ta gledalec šel kupit karto za to predstavo. • Na podlagi te verjetnosti se odloči, ali jo bo res šel kupit ali ne. • Če pride kupit vstopnico več gledalcev, kot je sedežev v dvorani, naključno izberi, kateri so vstopnico res dobili. • Na koncu leta izpiši skupno število prodanih vstopnic. • Verjetnost, da bi gledalec želel kupiti karto, je bila odvisna od: • časa predstave (ali je ob taki uri, ko je ta gledalec rad v kinu) • popularnosti filma • ali je film iz takega žanra, ki ga ta gledalec rad gleda • ali je bil zadnje dni ta gledalec že v kinu • ali je gledalec ta film že videl • Podrobnosti tega postopka (in tudi izvorno kodo ocenjevalnega programa) smo objavili tudi na naši spletni strani.

  37. Poti do rešitve • Pri tej nalogi ni neke očitne “pravilne rešitve” oz. postopka, ki bi dajal najboljše možne sporede • Prostor vseh možnih celoletnih sporedov je ogromen, v njem moramo nekako najti nek čim boljši spored • Uporabimo lahko razne tehnike s področja optimizacijskih metod: • Lokalna optimizacija, taboo search ipd. • Simulirano ohlajanje • Genetski algoritmi • Iskanje v snopu • Optimizacija z roji (swarms) • Najboljši naprej (best-first search), RBFS, ipd. • Paziti moramo, da nam postopek ne bo požrl preveč časa: • Prostor, ki ga preiskujemo, je res ogromen • Računanje kriterijske funkcije je precej drago • Mi smo dosegli precej dobre rezultate s preprostim požrešnim algoritmom

  38. Požrešni algoritem • Začnimo s praznim sporedom. • Dokler ne zapolnimo celega leta: • Preglej vse možne filme, ki jih smemo predvajati: • Za vsak film s simulacijo oceni, koliko vstopnic bi prodali, če bi dodali predstavo tega filma na konec našega sporeda. • Med vsemi filmi izberi najboljšega in ga dodaj na konec sporeda. • Zakaj “požrešen” (greedy) algoritem? • Nikoli se ne vračamo nazaj in spreminjamo delov sporeda, ki smo jih že sestavili • Pri vsakem filmu gledamo le, koliko vstopnic bi prodali zdaj – nič ne razmišljamo, ali je to dobro tudi na dolgi rok • Postopek je zelo preprost, vendar časovno precej potraten • V vsaki simulaciji se skriva zanka po vseh gledalcih

  39. Požrešni algoritem • Kateri film izbrati na vsakem koraku? • Najbolj očitna ideja: tistega, ki proda največ vstopnic. • Toda: filmi so različno dolgi. • Vstopnice za vse pa so enakovredne. • Če predvajamo krajše filme, jih bomo lahko v eno leto stlačili več in bomo mogoče prodali več vstopnic. • Zato je pametno gledati razmerje med številom prodanih vstopnic in trajanjem filma. • Izkaže se, da je v naših podatkih tudi nekaj “filmov”, ki so dolgi po manj kot 5 minut (reklame, videospoti) in so za ta kriterij zelo vabljivi • Nastanejo sporedi z 200000 predstavami… • ki pa skupno prodajo 3x toliko vstopnic kot sporedi, ki jih dobimo, če v vsakem koraku dodamo v spored film, ki proda največ vstopnic (ne glede na dolžino filma) • Na največjem testnem primeru se je naš postopek izvajal 16 dni. Za vseh 10 testnih primerov je porabil več kot en mesec procesorskega časa.

  40. Off-line naloga: Kino Razglasitev rezultatov

  41. Kino – rezultati • Tega dela tekmovanja so se žal udeležili le štirje tekmovalci • so bili pa zato ti toliko bolj navdušeni • 10 oddaj v zadnji uri, zadnja ob 23:58:54 • Točkovanje: • bilo je 10 testnih primerov • pri vsakem testnem primeru: • gledamo le najboljši prejeti spored vsakega tekmovalca • tekmovalce razvrstimo po oceni tega sporeda • prvi dobi 10 točk, drugi 8, tretji 7 • točke seštejemo po vseh testnih primerih

  42. Kino - rezultati • Animacija: za vsak testni primer je skupina stolpcev, ki kaže najboljše rešitve vseh tekmovalcev • Višina stolpcev pove, kako dobra je tista rešitev v primerjavi z najboljšo nam znano rešitvijo za ta testni primer

  43. Kino - rezultati • 1. mesto: Tomaž Hočevar (94 točk) • 2. mesto: Rok Kralj (86 točk) • 3. mesto: Domen Blenkuš (69 točk) • 4. mesto: Jan Berčič (19 točk)

  44. Posebna nagrada…

  45. Tekmovanje programov:Štiri v vrsto Blaž Novak

  46. Tekmovanje programov:“4 v vrsto” Naloga: sprogramiraj “pamet” za tekmovalca v znani igri 4 v vrsto 2 podkategoriji: tekmovanje na polju velikosti 7×6 tekmovanje na polju velikosti 20×20

  47. Tekmovalci Prejeli smo 7 rešitev, od tega 6 dijaških 3 v C#, 2 v Delphiju, 2 v C++ Ena od rešitev izločena iz končne razvrstitve na polju 7×6 zaradi prekomerne uporabe tuje kode Ena od rešitev izločena iz končne razvrstitve na polju 20×20 zaradi nestabilnosti

  48. Izvedba tekmovanja Igre na polju 7×6 smo zaradi točnosti rezultatov ponovili 30-krat Igre na polju 20×20 pa 20-krat Le 3 pari iger deterministični, ostali pri izbiri potez uporabljajo nekakšno naključnost 276.000 s procesorskega časa porabljenega za reševanje 1785 iger Točkovanje: Za vsak par igralcev: Za vsako igro dobi zmagovalec +1 točko, poraženec -1 točko (če je neodločeno, ne dobi nihče nič). Vzame se povprečje po vseh igrah. Na koncu seštejemo točke za posameznega igralca.

  49. Rezultati na polju 7×6

More Related