Top dvije novogodišnje optimizacije produktivnosti

Na osnovi vlastitog iskustva i raznih tekstova o produktivnosti koje sam vidio po webu ili u knjigama, zaključio sam da su ključna samo dva savjeta.

  1. Do the most important thing first each day.” Za svaki dan (ujutro ili večer prije) odluči koja je najvažnija stvar koju ćeš napraviti toga dana i onda tu stvar napravi odmah ujutro.
  2. Izdrži pet minuta. Kad mi se ne da započeti neki posao, nešto što ću morati raditi satima ili čak danima, onda mi se… well, ne da. Tu je, međutim, prisutna iluzija da će taj osjećaj “ne da mi se” potrajati sve to vrijeme, da ću se sve te sate ili dane morati boriti protiv njega kao što se borim sada na početku. Ali to je uglavnom, kao što sam rekao, iluzija! Jer, čim teškom mukom krenem raditi i izdržim pet minuta, muka najčešće nestaje jer se naprosto ufuram u posao i poslije, dok sam uronjen u posao, ne samo da je osjećaj “ne da mi se” davno nestao nego mi je čak teško stati, toliko da ponekad odgađam ručak ili nešto slično, samo da ne prekinem nit posla koju sam ulovio. Kad napravim posao, bude mi žao što sam prije toga toliko prokrastinirao, što sam toliko odgađao nešto što je zapravo lakše nego što se čini. Poanta glasi: ako ti se ne da, taj će osjećaj najčešće trajati samo prvih pet minuta rada. Izdrži pet minuta!

Kad sam ovo počeo pisati, imao sam na umu tri savjeta (top tri, jel, tko je vidio top dva?), ali zaključio sam da su ova dva dovoljna. Manje je više! Ipak, ako želite više (a tko ne želi više?), proguglajte “calendar blocking”. I ako želite unaprijed isplanirati 2021. godinu, ispunite planer za 2021. godinu s bloga Tee Zavacki o produktivnosti (TeaTime) koji toplo preporučujem. I pogledajte moj sličan post od prije godinu dana.

Kako vježbati?

Kako vježbati? WHO preporučuje barem 150 minuta tjedno aerobne aktivnosti (kao što su džogiranje, plivanje, bicikl) te vježbe jačanja mišića barem dvaput tjedno. Ali ovdje nije riječ o tom vježbanju, nego o natjecateljskom programiranju ili matematici. Na ovom sam blogu već pisao o raznim aspektima vježbanja, a sada to želim nekako sistematizirati.

Ovo pitanje tek rijetki shvaćaju dovoljno ozbiljno; čini mi se da većina pretpostavlja da je odgovor samo rješavaj zadatke ili nešto slično. Ali to je dobar odgovor samo ako:

  1. imamo dovoljno motivacije da redovito radimo;
  2. rješavamo i zadatke koji su dovoljno teški/izazovni, ne samo one koje znamo bez muke riješiti;
  3. imamo izvore novih znanja koji nam omogućuju napredak.

Bez prve točke nedostaje nam kvantiteta, bez druge točke kvaliteta treninga, a bez treće mentorski aspekt. Dobar trening sadrži sve tri komponente. Evo nekih prijedloga…

  1. Za prvu točku potrebna je disciplina. O njoj sam pisao u ovom postu. Ukratko, ako još ne radimo dovoljno redovito, za izgradnju navike dovoljno je svaki dan riješiti jedan lagani zadatak.
  2. Za drugu točku (izazov) potrebno je rješavati zadatke koji su otprilike toliko teški da uspijemo 50% puta, plus minus. Tako se postiže idealna razina motivacije:
    ChallengeMožete za sebe pronaći odgovarajuću razinu na Codeforcesu (npr. 2. zadatak na Div1) ili na HONI-ju (npr. 5. zadatak) i onda rješavati samo zadatke te težine. Jako je važno da neriješene zadatke upsolvate, tj. riješite nakon što pročitate opis algoritma (editorijal) ili pitate nekoga da vam objasni rješenje.
  3. Za treću točku postavlja se pitanje kako naučiti nove stvari. Tu su razna predavanja, knjige, web tutorijali, videi i tako dalje. Važan je i dobar mentor koji će vam, između ostaloga, ukazati na manjkavosti u vašim rješenjima i način na koji se nešto može bolje (vidi post code review).

Rečenica “pitajte nekoga da vam objasni rješenje” zaslužuje dodatni komentar. Nekima je lako pitati, ali sigurno ima onih koji misle da nemaju koga pitati, ili možda imaju, ali se boje da to možda nije pristojno, ne žele gnjaviti ljude, nisu s njima dovoljno dobri i slično. Možda i ne žele ispasti bedaci koji ne znaju riješiti zadatak ili im neka “sitnica” nije jasna. Odgovor je sljedeći. Malo zdrave “bahatosti” u smislu zapitkivanja i traženja pomoći je izvrsna životna kvaliteta. Dakle, bez ikakve zadrške, slobodno zapitkujte svoje poznanike ili čak nepoznanike, natjecatelje koji su malo stariji od vas, na messengeru, mailu ili gdje god. Ako vam je to bed, imajte na umu sljedeće. Osoba koju pitate najčešće neće misliti da je gnjavite, nego će vaše pitanje doživjeti kao kompliment svom znanju i iskustvu. Zamislite da vas netko traži takvu pomoć (kao što kad-tad i hoće), zar to nije lijep osjećaj? Nadalje, pitanjem ćete ostaviti dobar dojam zainteresirane i pristupačne osobe. To nije uvijek intuitivno onome tko se “usuđuje” pitati, ali je zbilja tako. Na primjer, reakcija nastavnika na studenta koji na predavanju postavi pitanje nije “šta ovaj sad hoće” ili “je li ovaj glup”, nego “napokon se netko ovdje ne boji komunicirati!” Ako onaj koga pitate ne želi ili ne može pomoći, najčešće će pristojno reći da nema vremena (ili će pristojno ignorirati) i sve štima. Medalje hrvatske informatike izviru upravo iz sustava u kojemu stariji natjecatelji pomažu mlađima. Neki su gnjavili mene, ja sam svojedobno gnjavio Žužića i Sluganovića, prije toga je Žužić gnjavio Kalinovčića, a danas novi klinci gnjave nove face. Ljudi koji ne žele nikoga gnjaviti gnjavež su sami sebi.

 

Tip of the day: stari bilteni

Kada je napolju 30+ stupnjeva, a klimu nemamo ili nam ne radi, mozak se od vrućine razlijeva bespućima pustoši i pustopoljine i nemamo snage za rješavanje zadataka. Ipak, možda još nismo toliko otopljeni da ne bismo mogli barem čitati rješenja (opise algoritama i kodove) dobrih zadataka iz kojih množemo mnogo naučiti.

Naravno da toga na webu ima napretek, ali ovdje bih uputio na jedan dobar domaći izvor za koji vrlo malo ljudi zna, a to su stari bilteni sa HSIN-ovih ljetnih i zimskih škola informatike, u kojima se često u opisu pojedinih radionica (Algoritmi, Olimpijci…) opisuju odabrani zadatci s tih radionica s rješenjima, a nađe se i drugih trikova i zanimljivosti. Primjer je recimo Bilten iz 2010. gdje od 58. stranice legendarni mentor Luka Kalinovčić objašnjava vrlo poučne zadatke Bugs IntegratedIcerinkMonkeys. A ostali bilteni nalaze se ovdje!

Tip of the day: testiranje

Nekada na važnim natjecanjima nije bilo full feedbacka pa smo nervozno čekali rezultate tumarajući po hodnicima, koji su uglavnom dolazili isprintani (rezultati, ne hodnici) za svakog natjecatelja posebno – ishodi po pojedinim primjerima. I danas je slična situacija na županijskom i na HONI-ju gdje nema feedbacka, ali nekada je tako bilo i na državnom (koje se zvalo DMIH), na HIO-u, IOI-u i svugdje. Full feedback pojavio se, ako se ne varam, na IOI-u 2010. Na CEOI-u 2013. u Primoštenu još uvijek ga nije bilo, a na državnom je uveden 2015. gdje je ključnu ulogu odigrao Ante Đerek, između ostalog motiviran e-mail prepiskom nakon žalbi sa županijskog. U jednom od tih mailova Stjepan Glavina napisao je poznatu rečenicu: “Tradicionalni tip natjecanja mora nestati.”

Ovakvi incidenti su razlog zašto mislim da tradicionalni tip natjecanja (HONI, državno, CEOI, IOI prije 2010.) mora nestati. A nisam jedini koji tako misli [1]. Bodovanje je vrlo nepravedno. “Manje” kriva rješenja znaju dobivat više bodova od “više” krivih. Zna se desit i da točna rješenja s malim bugom dobiju manje bodova od potpuno krivih, ili čak nula bodova. Faktor (ne)sreće je prevelik. Drame s bugovima se događaju na svakom takvom natjecanju.

Prije full feedbacka, testiranje rješenja “s brutforsom i generatorom” bila je standardna stvar koju su jači natjecatelji tijekom natjecanja radili na svim zadatcima gdje je to imalo smisla. Jednom sam komentirao da nerado testiram jer volim misliti da sam riješio zadatak, barem tih nekoliko sati, umjesto da si testiranjem srušim rješenje. “Kurdija, to je i ideja”, odgovorio mi je Žužić odmahujući glavom u nevjerici.

Full feedback ima i određenih mana. Neki misle da je njime djelomično izgubljen važan dio natjecanja – spomenuto testiranje, te da rezultati dobiveni odmah “na pladnju” nisu nešto što je inače realno. S organizacijske strane ima više posla – zadatci moraju biti teži nego inače (jer natjecatelji zbog feedbacka troše manje vremena i manje griješe), s više parcijala da se dobije dobra disperzija bodova (koja se prije lakše dobivala zbog raznih neotkrivenih bugova), a greška u evaluaciji ili testnim primjerima košta više nego prije jer utječe na tijek natjecanja.

Osim na onim natjecanjima gdje još uvijek nema feedbacka (mislim da i Codeforces ulazi u tu kategoriju), danas testiranje koristimo i onda kada nam evaluator kaže da rješenje ne valja, ali ne znamo zašto pa moramo naći primjer na kojemu pada. Errichto dobro objašnjava kako se to radi:


Ugrubo i sažeto, evo bash skripte kakvu sam nekada koristio (njegova je malo drugačija):

echo > o1  # napravi prazan prvi output
echo > o2  # napravi prazan drugi output
while diff o1 o2; do     # dok su outputi jednaki
    ./gen.py > t         # generiraj random primjer t
    ./test.exe < t > o1  # o1 = rjesenje(t)
    ./brute.exe < t > o2 # o2 = brutfors(t)
    printf '.'           # ispisi tocku za svaki testirani primjer
done

Poziva se iz Linux terminala:

bash testiraj.sh

… ili (nakon postavljanja chmod +x testiraj.sh):

./testiraj.sh

Update: sad uočavam da sam riječ testiranje u dvama nedavnim postovima (ovom i ovom) koristio u značenju evaluacija tj. isprobavanje na službenim testnim primjerima, dok se u ovom postu testiranje odnosi na stress-testing rješenja za vrijeme natjecanja kada službeni testni primjeri još nisu dostupni. Tu dvoznačnost mogao bih otkloniti tako da u prethodnim postovima svugdje napišem evaluirati umjesto testirati, ali to mi se ne da i vjerojatno je i ovako jasno o čemu se radi.

Tip of the day: testiranje na pythonovski

Kao nastavak prethodnog posta Tip of the day: testiranje zadataka sa HSIN-a, ovdje ću testiranje rješenja napisati u Pythonu (a ne u Bashu), i to s dodatnim funkcionalnostima kao što su automatsko preuzimanje testnih primjera, mjerenje vremena izvođenja i paralelizacija. Ipak preporučujem da najprije pročitate navedeni post radi razumijevanja načina pozivanja programa, preusmjeravanja inputa/outputa i diff-anja, što ćemo koristiti i ovdje. Osim samih skripti, ideja je i pokazati neke mogućnosti Pythona.

Želimo, za početak, zaobići ručno preuzimanje zip datoteke i ručno extractanje odgovarajućih testnih primjera iz nje. Nema problema! Evo skripte download.py, koja kao argumente prima ime zadatka i URL zip datoteke s njegovim testnim primjerima:

#!/usr/bin/python3
from io import BytesIO
from zipfile import ZipFile
from urllib.request import urlopen
from sys import argv

ime_zadatka = argv[1]
url = argv[2]

resp = urlopen(url)
zipfile = ZipFile(BytesIO(resp.read()))
for filename in zipfile.namelist():
if filename.startswith(ime_zadatka):
zipfile.extract(filename, '.')

Primjer preuzimanja testnih primjera za zadatak Modulo s 1. kola HONI-ja 2006.:

./download.py modulo https://hsin.hr/honi/arhiva/2006_2007/kolo1_testpodaci.zip

Ishod će biti stvaranje datoteka modulo/modulo.in.1, modulo/modulo.out.1 i tako dalje, gledajući iz direktorija u kojem je skripta pokrenuta. Izmjenu skripte po vlastitim željama ostavljamo čitateljici za vježbu.

Ako se nalazimo unutar direktorija u kojemu je naše rješenje i testni primjeri, skripta koja testira sve primjere, usput mjereći vrijeme izvođenja za svaki primjer, izgledala bi primjerice ovako:

#!/usr/bin/python3
from os import listdir, popen
from time import time
from sys import argv

ime_zadatka = argv[1]
rjesenje = argv[2]

for filename in listdir('.'):
if '.in.' in filename:
print('\nTestiram {}...'.format(filename))
start_time = time()
popen('./{} < {} > tmp.out'.format(rjesenje, filename)).read()
print('Vrijeme = {:.3f} sekundi'.format(time() - start_time))
p = popen('diff -w tmp.out {}'.format(filename.replace('.in.', '.out.')))
print(p.read() or '---------- OK ----------\n')

Dakle, za svaku *.in.* datoteku (ulazni primjer),  unutar popen-a kao novi proces pokrećemo naše rješenje, preusmjeravamo taj primjer na ulaz, a naš izlaz u datoteku tmp.out koju potom uspoređujemo (diff) sa službenim *.out.* izlazom. Ako je diff prazan, ispisujemo OK. Za mjerenje izvođenja ključna je funkcija time.time() koja daje trenutačno vrijeme u sekundama. Poziv skripte za zadatak Herman izgledao bi npr. ovako:

./test.py herman herman.exe

Nedostatci? Primjeri se neće nužno izvesti prirodnim redoslijedom i možda je moguće usporedno provjeravati više primjera (na više jezgri procesora) radi bržeg testiranja. Obje stvari možemo riješiti tako da napravimo četiri procesa (multiprocessing.Pool(4)) od kojih svaki paralelno testira svoj dio testnih primjera i vraća ishod kao string (npr. “Primjer 1OK, 0.1 sekundi“), koje onda na kraju možemo sortirati abecedno pa će primjer 1 biti prvi.

#!/usr/bin/python3
from os import listdir, popen
from time import time
from sys import argv
from multiprocessing import Pool

ime_zadatka = argv[1]
rjesenje = argv[2]

def testiraj(filename):
output = '\nTestiram {}...\n'.format(filename)
ekstenzija = filename.split('.')[-1]
start_time = time()
popen('./{} < {} > tmp{}.out'.format(rjesenje, filename, ekstenzija)).read()
output += 'Vrijeme = {:.3f} sekundi\n'.format(time() - start_time)
p = popen('diff -w tmp{}.out {}'.format(ekstenzija, filename.replace('.in.', '.out.')))
output += p.read() or '---------- OK ----------\n'
return output

with Pool(4) as p:
ishodi = p.map(testiraj, [filename for filename in listdir('.') if '.in.' in filename])
for i in sorted(ishodi):
print(i)

I ovdje se neke stvari mogu doraditi, može se dodati timeout tj. ograničiti vrijeme izvođenja, a moguće se i pobrinuti da herman.in.10 ne dođe prije herman.in.2 iako je prije po abecedi. Sve to i mnogo više ostavljamo… znate već.

Tip of the day: testiranje zadataka sa HSIN-a

Mnogi od mojih postova sadrže poveznice na zadatke sa HSIN-a koji (barem zasad) ne postoje ni na kakvom evaluatoru. Zato je smanjena motivacija za njihovo rješavanje: nije moguće jednostavno submitati rješenje i odmah dobiti povratnu informaciju, nego je nužno pronaći i skinuti zipane testne primjere sa hsin.hr i lokalno ih isprobati.

Ovo “isprobati”, naravno, ima svoje nijanse. Mnogi znaju samo kopipejstati primjer u program, što je zbilja odvratno. Određen broj natjecatelja zna prosljeđivati jedan po jedan primjer u program koristeći komandnu liniju, te naredbom (diff ili fc) provjeriti podudaranje izlaza. Tek manji broj njih zna to učiniti za sve primjere odjednom, koristeći skriptu. Pokažimo kako se to radi!

Naprije na sporiji način. Dakle, nakon što smo zipane primjere pronašli negdje na https://hsin.hr/natjecanja.html ili na https://hsin.hr/honi/arhiva/ te ih otpakirali, potrebno je u terminalu navigirati do tog direktorija (npr. cd kodovi/herman ako se zadatak zove Herman). Ako smo rješenje kompajlirali tako da se program zove herman.exe, u terminalu ga pokrećemo na sljedeći način:

./herman.exe

(na Windowsu mislim da je bez ovoga ./). Sada bi se primjer unio “s tipkovnice” ili kopipejstao, što ne želimo. Prosljeđivanje primjera (npr. herman.in.1) izravno u program činimo na sljedeći način:

./herman.exe < herman.in.1

… i odmah vidimo što nam program ispisuje. Želimo li ispis u datoteku, pišemo npr. ovako:

./herman.exe < herman.in.1 > izlaz.txt

Tu će datoteka izlaz.txt biti stvorena ako ne postoji, ili prepisana ako postoji. Usporedbu tog našeg ispisa sa službenim izlazom činimo na sljedeći način:

diff izlaz.txt herman.out.1

(Mislim da je na Windowsu fc umjesto diff). Želimo li zanemariti whitespace, dodajemo opciju -w. Ako diff ne ispiše ništa, znači da su datoteke jednake (rješenje je točno), a inače se ispiše razlika.

To bi valjalo ponoviti za svaki primjer, npr. za peti primjer:

./herman.exe < herman.in.5 > izlaz.txt
diff -w izlaz.txt herman.out.5

Mnogo bolje od kopipejstanja, ali i dalje naporno, pogotovo ako postoji 30 primjera ili ako imamo clustere pa primjeri imaju nastavke 1a, 1b, 1c, 2a… No evo skripte koja to radi sve odjednom, nazovimo je npr. test.sh:

for input in herman.in.*; do
    extension="${input##*.}"
    output=herman.out.${extension}
    ./herman.exe < $input > izlaz.txt
    diff -w izlaz.txt $output
done

(Za Windows nemam pojma.) Da bismo je mogli pokrenuti, treba joj dodati executable flag:

chmod +x test.sh

… i potom je pokrećemo kao što bismo pokrenuli i program:

./test.sh

Riječ je o ružnom jeziku Bash koji je dobar za jednostavno Unix/Linux skriptiranje i ni za što drugo. U njemu i razmaci rade probleme.

Unaprijedimo našu Bash skriptu s još nekoliko stvari. Recimo, želimo da nam ista skripta može poslužiti za svaki zadatak, a ne da svaki put moramo mijenjati ime zadatka u skripti (u ovom slučaju Herman). Rješenje je uvesti varijablu umjesto tog imena, a tu varijablu pišemo kao $1 jer je riječ o prvom argumentu koji ćemo napisati desno od imena skripte pri njezinom pokretanju:

./test.sh herman

A skripta onda izgleda ovako:

for input in $1.in.*; do
    extension="${input##*.}"
    output=$1.out.${extension}
    ./$1.exe < $input > izlaz.txt
    diff -w izlaz.txt $output
done

Ako želimo “customizirati” i naziv rješenja, za koji smo dosad pretpostavljali da je oblika imeZadatka.exe, možemo dodati još jedan argument $2:

for input in $1.in.*; do
    extension="${input##*.}"
    output=$1.out.${extension}
    ./$2 < $input > izlaz.txt
    diff -w izlaz.txt $output
done

… nakon čega je pokrećemo npr. ovako:

./test.sh herman herman.exe

Možemo napisati i varijantu s trećim argumentom – rednim brojem primjera – ako želimo testirati samo određeni primjer. Evo i varijante koja ispisuje koji su primjeri prošli te se zaustavlja na prvom primjeru koji je pao:

for input in $1.in.*; do
    extension="${input##*.}"
    output=$1.out.${extension}
    ./$2 < $input > izlaz.txt
    if diff -w izlaz.txt $output; then
        echo $input 'prosao'
    else
        echo $input 'pao'
        exit 0
    fi
done

Primjer outputa:

herman.in.1 prosao
herman.in.2 prosao
herman.in.3 prosao
1c1
< 0
---
> 565315
herman.in.4 pao

Ni ja ne znam Bash, većinu ovoga sam izguglao. Ako netko ima primjedbi ili prijedloga poboljšanja, neka napiše u komentarima. Za neki od idućih postova nastojat ću napisati Python skriptu koja radi isto, a i više od ovoga.

Iza kulisa HONI-ja

Voditelji ovogodišnjeg HONI-ja, Ivan Paljak i Marin Kišić, odlučili su javno objaviti repozitorij u kojem su rađeni zadatci. Evo ga ovdje:

https://github.com/mkisic/HONI-19-20

Za one koji to nikada nisu radili, ovo je dobra prilika da dobiju neki uvid u izradu zadataka za informatička natjecanja. Osim samih tekstova i rješenja, autori pišu generatore testnih primjera, razna polurješenja da bi provjerili nose li očekivani broj bodova ili konstruirali primjere koji ih ruše, kodiraju validatore koji provjeravaju zadovoljavaju li primjeri uvjete iz teksta zadatka i jesu li u dobrom formatu, pišu checkere za one zadatke gdje output nije jednoznačan itd. Kao primjer što se sve ponekad napravi za jedan zadatak, pogledajte direktorij za zadak Skandi (6. kolo).

Najprije, što je uopće repozitorij? Riječ je o folderu u kojemu više suradnika zajedno radi, a sve promjene prate se putem tzv. version control sustava (kao što je git) koji omogućava praćenje tko je i kada što dodao, promijenio i slično. Ljudi drže takve repozitorije (što javne, što privatne) na stranicama kao što su GitHub, Bitbucket i Gitlab. Version control sustavi su norma u svijetu programiranja i koristi ih svaki iole ozbiljan projekt jer inače nastane kaos. Korisni su čak i kad samo jedna osoba radi na projektu, jer imaju mogućnost undo-a tj. vraćanja na prethodnu verziju bilo koje datoteke. Sram me to priznati, ali za Državno 2018. (pod mojom palicom) koristili smo Google Drive. Ručni upload, ručni download, živi užas, ne znam što mi je bilo. Jednom i nikad više. Ovdje sve ide lijepo glatko iz komandne linije, naravno, na Linuxu.

Još jedan od važnih ovdje korištenih alata je LaTeX za tekstove zadataka. On omogućava automatizaciju mnogih stvari, npr. probni primjeri ne moraju se pisati na dva mjesta (u tekstu i u datotekama) nego se automatski kopiraju u tekst, svaki je zadatak u svojoj .tex datoteci čime se lakše prate promjene i slično. Ove godine i školsko i županijsko bili su u LaTeX-u (priznajem, prethodne dvije godine bio je Word u igri). Evo primjera glavne .tex datoteke za 6. kolo koja, kao što vidite, uključuje po jednu datoteku za svaki zadatak (npr. Trener). To se onda pretvara (“kompajlira”) u PDF naredbom pdflatex. Matematičari već znaju da je LaTeX nezaobilazan, ali to zapravo vrijedi i za računarstvo i većinu stručnih/znanstvenih disciplina.

Onda su tu generatori testnih primjera koji se najčešće pišu u Pythonu (jer je najlakše) i nastoji se izgenerirati sve primjere u jednom pokretanju generatora. Ovdje je primjer generatora za zadatak Trener. Također u Pythonu piše se i validator primjera (npr. ovaj) koji mora napisati druga osoba; on provjerava da su primjeri u ispravnom formatu (uključujući i razmake) i da zadovoljavaju sva ograničenja, uključujući i ona iz sekcije Bodovanje (npr. N < 100 u 50% primjera). Kao što se može uočiti, za generatore i validatore postoje templateovi koji pomažu da se oni brže napišu. Validator je uglavnom lako napisati, ali ponekad se moraju provjeriti i netrivijalni uvjeti poput zahtjeva da je graf povezan ili još težih uvjeta.

I naravno, tu su brutforsi, alternativna rješenja, rješenja za parcijale iz bodovanja, “prevare” (greedyji, heuristike) i ostala rješenja za koje se mora provjeriti koje primjere osvajaju. Za one zadatke gdje natjecateljev output treba programski provjeriti (jer nije jedinstven) pišu se checkeri (npr. ovaj) koji provjeravaju je li output točan. Oni su poseban izazov jer se ne smiju srušiti i moraju raditi za sve neočekivane slučajeve (pogrešan format, manjak ili višak ispisa, očekuje broj a dobije string i sve ostalo).

Previše posla? Ne uvijek. Za većinu zadataka (pogotovo one lakše) ne pojavljuju se baš svi od navedenih izazova. Nekad tekst zadatka može biti kratak i jednostavan, nekad je lako generirati primjere (baciš neki random i bok), nekad ih je lako validirati, nekad je lako napisati brutforse, checker često nije potreban itd. Na kraju, ako je dovoljno zainteresiranih ljudi i ako počnu raditi na vrijeme, ispadne OK i, naravno, bude jako zabavno.

Tip of the day: Linux

Većinu stvari u životu bolje je naučiti prije nego poslije.

Jedna od njih je pravilno tipanje. Nakon što naučite koji prst mora pritisnuti koju tipku da bi vam tipkanje bilo brže i ugodnije (a sami intuitivno nećete to skužiti), bit će vam žao što ste ikada tipkali pogrešno.

Druga i još važnija stvar je Linux, ako planirate jednom otići na međunarodno natjecanje ili se planirate baviti ikakvim programiranjem ikada u životu.

Preporučio bih i ostale Errichtove objave: https://www.youtube.com/channel/UCBr_Fu6q9iHYQCh13jmpbrg

(Naravno, postoji još stvari u životu koje je bolje naučiti prije nego poslije. Od ljubavi do meditacije. Izguglajte.)

Algoritmi u Pythonu

Vrijeme je, napokon, da i ovdje reklamiram knjigu koju smo Nikola i ja ljetos objavili. Riječ je o priručniku Algoritmi u Pythonu, namijenjenom darovitim osnovnoškolcima i onim srednjoškolcima koji tek uče algoritme. Evo linka:

https://shop.skolskaknjiga.hr/algoritmi-u-pythonu-prirucnik-za-ucenje-racunalnog-razmisljanja.html

Za zainteresirane, evo sadržaja:

Screenshot

Od ljudi koji su nam se javili, povratne informacije su izvrsne i čini se da knjiga jako dobro ispunjava svoju svrhu. Jako cijenimo svaki komentar, a pogotovo primjedbu, budući da se nadamo da će priručnik doživjeti još koje izdanje. Tko god je čitao ili bude čitao knjigu, pozivamo ga da nam javi što god mu zapne za oko, bilo pozitivno bilo negativno. Listu ispravaka uočenih pogrešaka održavamo ovdje.

Knjiga sadrži pristupne podatke za evaluator (Pythor) koji je napravio i održava Matej Ferenčević. On zasad sadrži samo zadatke s HONI natjecanja, ali plan je da se dodaju i svi zadatci s novijih službenih informatičkih natjecanja u Hrvatskoj, kao i neki zadatci koji se pojavljuju samo u knjizi Algoritmi u Pythonu.

Ako imate kakvih pitanja o knjizi, napišite u komentar, rado ću odgovoriti. Za kraj, riječ-dvije o mojoj motivaciji za pisanje priručnika, kao i za ovu objavu: cilj je napraviti dobru stvar i proširiti znanje na najbolji mogući način. “Zarada” od ovakvih knjiga je takva da se, s obzirom na uloženo vrijeme i trud, pisanje uopće ne isplati (ako razmišljate na taj način). No gledajući pozitivan učinak kod čitatelja, itekako se isplati.

Top pet novogodišnjih optimizacija

Hello friends. The year is almost over so I have prepared the top 10 optimizations of 2017 for your viewing pleasure. Without forthor ado, let us begin.

—bukefala, 7.7.2017.

Godina se bliži kraju. Po uzoru na nenadmašni post gospodina V. K. o najboljim optimizacijama 2017., ovdje objavljujemo top pet (n)ovogodišnjih optimizacija. No budući da je ovaj blog odavno zastranio u meta vode, riječ je nažalost samo o metaoptimizacijama, tj. optimizacijama informatičke produktivnosti. Jebiga. Bez daljnjeg odugovlačenja, počnimo.

  1. Zadatak dana. Izvrsna novogodišnja odluka: svaki dan riješiti jedan zadatak. Za motivaciju si naručite npr. dnevnik navika koji, između ostalog, ima mjesečnu stranicu u koju upisujete jedan redak za svaki dan tekućeg mjeseca (line per day). Naravno, tko bi pisao cijelu rečenicu – puna rečenica u ovo doba instant komunikacije krupan je zalogaj – ali dovoljno je da u redak zapišete ime zadatka koji ste toga dana riješili. Dakle, ne u neki elektronički dokument, nego pravom olovkom u pravu bilježnicu, u tome je ljepota. Vaša navika tako postaje materijalna i vaša vas draga bilježnica svakodnevno poziva da je ne ostavite neispunjenu.linePerDay
    ——–
  2. Never miss twice. Za praćenje navike rješavanja zadatka dnevno, ili bilo koje druge navike koju želimo usvojiti, možemo koristiti i jednostavniju stvar od line per day iz prethodne točke. Napravimo papirnatu tablicu (habit tracker) u koju za svaki dan stavljamo iksić ako smo toga dana odradili naviku. Cilj je ne prekinuti niz iksića ili, ako se on prekine (a hoće jer nismo savršeni), da onda to ne bude dva dana zaredom. Ja sam si svoje tri tablice (za tri navike, nije važno koje) za 2020. godinu već pripremio i jedva čekaju da ih počnem ispunjavati:imag0949
    Ponovno, važno je da ovo ispunjavate olovkom u bilježnicu, a ne na ekranu. Ako ne razumijete zašto, isprobajte jedno i drugo i bit će vam sasvim jasno koji iksić vam je veći gušt napisati.
    ——–
  3. Natjecateljski dnevnik. O upsolvingu već sam pisao, ali evo dodatnog savjeta: u bilježnici/dnevniku analizirajte svoj performans na svakom natjecanju (ili simulaciji) na kojemu se nađete. Znamo da su važna natjecanja blizu pa je ovo možda dobar čas za takav savjet. Ne mislim na dojmove tipa “bilo je teško, nisam imao koncentracije”, nego na preciznu, objektivnu analizu što ste i zašto napravili na kojem zadatku. To su olimpijci ispunjavali na IOI pripremama u online dokumentu nazvanom Dnevnik simulacija. Evo primjera jednog takvog zapisa (Adrian Beker na jednoj simulaciji 2017. godine):

    Procitao sam sve zadatke te krenuo od drugog jer mi se cinio najjednostavnijim. Nakon nekog vremena uspio sam smisliti cijelo rjesenje te sam ga bez vecih problema nakodirao, tako da je acc pao za nesto manje od sat vremena. Zatim sam presao na treci zadatak, smislio prve dvije parcijale i odlucio ih nakodirati. To se nepotrebno oduljilo zbog glupog buga, tako da mi je ostalo manje vremena nego sto sam predvidjao. Ucinilo mi se da je predzadnja parcijala dosta laksa od cijelog rjesenja pa sam ju pokusao smisliti, ali sam negdje u toku odlucio ipak nakodirati prve dvije parcijale na prvom jer su se cinile trivijalnima. Na kraju sam na tome dobio TLEove, vjerojatno zbog prevelike konstante. Zadnjih nesto manje od sat vremena proveo sam dovrsavajuci ideju za treci i kodirajuci rjesenje koje je trebalo dobiti 80%, no bilo je preruzno da bih stigao u tom vremenu.

    Poanta je u tome da razvijete natjecateljske metavještine: taktičnost, bistriji um i da u svakom trenutku točno znate što, kako i zašto rješavate. A i psihološki će vam biti lakše ako nakon neuspjeha precizno zapišete što, kako i u kojem trenutku je pošlo krivo, umjesto da ostanete u onom nejasnom, maglovitom i muljevitom osjećaju “sjebo sam, ne vrijedim” i tugaljivo bauljate hodnicima u potrazi za smislom života.

  4. Metaoptimizacije iz arhive Blogaritma. Svašta sam nadrobio u ove nepune dvije godine (od prvog aprila 2018. otkad blog postoji), od čega ima i korisnih stvari. (Iako su one druge, beskorisne stvari ono što me više veseli.) Na primjer, opširnije o navici zadatak dnevno govori ovaj post od prije godinu dana. Ako ste baš hard core, pročitajte i knjigu koju u njemu preporučujem.
    ——–
  5. Teina radna bilježnica za novogodišnje odluke. Zgodna i korisna poveznica s bloga koji toplo preporučujem. Inače, Tea je vrlo uspješna diplomirana FER-ovka koja je, tko bi rekao, programiranju “dala nogu” i odlučila raditi stvari koje više voli. Spomenimo za kraj, eto, i takvu novogodišnju mogućnost.