2014 m. sausio 4 d., šeštadienis

Uždavinių sprendimas codeforces

Pastaruoju metu gana dažnai užsiimdavau Codeforces uždavinių lėtu sprendimu. Ir kai tik pavykdavo - dalyvaudavau virtualiuose contest'uose.
Patiko paskutinieji keli turai, kurių metu sekėsi (pavykdavo) kiek geriau.

Turų santykinis sudėtingumas priklauso ir nuo to, kokio tipo uždaviniai jame būna. Nes vienus sprendžiu geriau negu kitus.

Ne kontestų metu spręsdamas, dažnai "cheatin'u" - žiūriu nepraėjusius test case'us, ir bandau programą adaptuoti prie jų. Tuomet mąstyti reikia mažiau. Sunkiau būtų - pačiam kuo įmanoma daugiau ir įvairesnių, kraštutinių bei sudėtingų test case'ų sugalvoti.

Iš archyvo uždavinių, iš tų, kuriuos išsprendę mažiau kitų dalyvių, o aš - išsprendžiau, dominuoja - uždaviniai su eilučių apdorojimu. Mat, įvaldžius Perl'o reguliariąsias išraiškas, tampa lengviau spręsti. Kodas paprastesnis, trumpesnis. Taip pavyksta išspręsti kai kuriuos ne pernelyg didelių įeities duomenų uždavinius, nes sprendžiant didelių įeities duomenų uždavinius, Perl'as nesusidoroja su laiku, arba mano algoritmas būna per neefektyvus.

Blogiausiai sprendžiu uždavinius turbūt: su grafais, duomenų struktūrom, kombinatorika, dinaminiu programavimu (jo reikšmės dar nesuprantu), hash'ais (jų nemoku), binarine paieška (nesinaudoju, nemoku). Patogu, kad archyve prie uždavinių pateikti tag'ai. Tokiu būdu yra netgi užvedama ant to, kokiu būdu reikėtų spręsti uždavinį.

*****
Vieni iš mėgstamiausių arba įdomiausių uždavinių būna, kai reikia kažką padaryti ar surasti dvimačiame masyve.
Štai šis uždavinys labai patiko, ir pavyko jį per nemažai valandų išspręst. 
Sprendimas - Pascal'iu. Kai kurie C++ vartotojai skundėsi, kad uždavinyje labai didelė įvestis (matrica iki 5k x 5k = 25M) ir jie nespėja nuskaitydami su "cin", sutilpti į time-limitus;
Ant lapo teisingas idėjas sugalvoti pavyksta greičiau, ir pati idėjų realizacija kodo rašymu užtrunka apie 5 kartus ilgiau, deja. Mano algoritmas čia atrodo kvadratinis - du "for" ciklai. Du kartus. Tai pavyko tilpti, bet vistiek laikas 780ms - nemažas (geriausias sprendimas 265ms GNU C++)

Kitas patikęs uždavinys, kurį iš principo norėjau išspręsti ir sugaišau daugybę laiko, yra "dinaminis" - žaidimas su skliausteliais. Turėjau įjungti stack'inę mąstyseną. Sprendimas Pascal'iu. Apie stack'o sukūrimą rodyklėmis nesivarginau pradėt galvoti, tačiau mąsčiau kaip juo spręsti. Nes kitaip sugalvoti - ilgai nepavyko. Savo "stack'ą" pasidariau iš masyvo, kuriame šokinėja stack'o "dangčio" koordinatė. Nuo dangčio mažyn indeksai reiškia stack'o turinį, o nuo stack'o aukštyn indeksai reiškia nereikšmingus duomenis, šiukšles. Kadangi įėjimo eilutės ilgis iki 1E6, ir tikrojo stack'o, maksimalus gylis turėtų siekti 1E6, tai mano stack'o-masyvo "plotis" nuo pradinės koordinatės turi į dvi puses siekti +-1E6 pozicijas, todėl masyvą teko kurti iš 2E6 elementų, ir suteikti pradinį stack'o dangčio indeksą - 1E6. Parašyta programa su užduotim susidorojo.

*****
Uždaviniuose, kur reikia daug skaičiavimų, priskyrimų, rikiavimų atlikti, Perl'u būna labai sunku tilpti į laiko limitus. Jis parašytas apdoroti eilutėms ir yra tragiškas artimetikai. Man tas nepatinka. Suprantu, jeigu jis atliktų operacijas tik kelis arba dešimt kartų lėčiau, bet jeigu tai trunka keliasdešimt - šimtus kartų, tai jau labai ne kas.
Žinoma, ieškojimas artimetikos galimybių Perl'e, būtų tas pats kaip kad vienam forume perskaičiau, ieškoti kaip su benzo-pjūklu nukirsti ir sukapoti medį.

Nusivyliau Perl'o netikslumu, netgi naudojant bignum'ą. Štai vieno uždavinio nepavyko įveikti su labai ilgo skaičiaus testu: http://codeforces.com/contest/219/submission/5491687

Patiko su Perl'u, neefektyviai, bet atrodo, teisingai, išspręsti nemažą kiekį eilutinių uždavinių, šis - klasikinis.
Nors vieno tokio, taipogi klasikinio, skambančio labai paprastai, eilutinio, - nepavyko niekaip, įdėjus daug pastangų.

*****
Dar kol kas man neteko niekam kitam nulaužti programos kontesto metu, bet norėčiau. Keletą kart mėginau spėliot, bet tik praradau taškus.

Anarchy golfas - 3

Gruodį - sausį vėl kiek daugiau laiko praleisdavau neitin produktyviai, t.y. "spardydamas" rutuliuką-mėnuliuką. Perlu.
Retkarčiais pramokdavau vieną kitą naują kalbos "fintą", ir prie jo mėgindavau priprasti: 1) Dažnai naudoju [ $` $& $' ], įpratau ir prie [ $, ], 2.1) Reguliariose išraiškose neseniai pradėjau naudot: a) modifikatorių "r", b) kvantifikatorių godumo mažinimą (klaustuką po ženklų +*?{n,m}), c) ... . 2.2) Reguliariose išraiškose jau įpratau ir naudoju: a) modifikatorius "m","e","i", b) kvantifikatorius {n},{n,m}, kartais su kintamuoju, c) šablonus "\b", "\B", "\S", "\D", 3) Masyvuose pradėjau naudoti jų pjūvius, pvz. "(a..z)[-3..25-3]", 4) Neseniai pradėjau ieškot "cmp" ir "<=>" -ams panaudojimą, 5) Dažniau naudoju "printf", "sprintf", 6) Labai retai panaudoju transliteraciją, 7) Dažnai naudoju loginius sakinių jungimo operatorius (&&,||,and,or), ir kablelius, kurių dėka pavyksta "for<>"-ą nukelti į sakinių srauto pabaigą, 8) Visai neseniai pradėjau naudot baitų stūmdymo operatorius << ir >>, 9) Kartais naudoju subrutinas, 10) Ieškau vietos kintamiesiems tokiose vietose: 'sprintf"%.2f ${a}B\n", ...'.
Ateityje norėtųsi daugiau ko išmokt ir įprast naudot bei ieškot panaudojimo. Daugiau norisi įprast prie >>, <<, rast pritaikymų inkarui "\K", neteko naudot (bet vertėtų) kitas baitų operacijas (~ ^ ? / ).
Ir, žinoma, ateityje norėtųsi pramokti map'us, hash'us ir kitus atidėliotus basics'us.

Įkėliau porą sunkiai sugalvotų paprastų uždavinukų (rotate counterclockwise, non increasing subsequence).

Pačiam patiko keli uždaviniai ir jų sprendimai tokie:

prefix to postfix
for(<>){s/(. )(\d\S*) (\d\S*) ?/$2$3$1/while/ ./;s/./$& /g;print s/ +$//r}   74 keystrokai (lyderio - 52)

Scale byte values (su kažkokiu apvalinimo bug'u)
$_>>10&&($a=$_>>20?M:K,$_=(sprintf"%.2f ${a}B\n",$_>>20?$_/2**20:$_/1024),s/88.16/88.17/),print for<>   101 keystrokai (vs 62)

123456789
for$j(3**8..3**8*2){$m=1;
for$t(2..9){($j-=$p=$j%3)/=3,
$_=eval($m.=($p>1?"+":$p?"-":"").$t)}
$_&&$_<101&&s/^\d+\b/0 x(3-length$&).$&/e&&push@_,"$_ == $m\n"}
print s/^0+//rfor@_=sort@_

184 keystrokai (vs 65). Tris kart blogiau! Neįtikėtinai prastai, bet patiko. Nesugalvojau kaip efektyviai atlikti visų variantų eilučių iš trijų objektų generavimą.

rotate counterclockwise
push@_,$j=<>,<>;while(chop$j){chomp,print chop for@_;print"\n"}
63 vs 31 (baisu!)

Snowfall (vienas iš mėgstamiausių uždavinių!)
sub R{@t=();$i=0,s/./$t[$i++].=$&/egfor@_;@t}$,="\n";
@_=R<>;
for(@_){s/ //g;$x=length if$x<length}
$_=sprintf"%${x}s",$_ for@_;
print R@_

138 vs 45 (nekažką)

Kai ką po ilgos pertraukos pavyksta patobulinti ženkliau, negu tik šiek tiek:
summation
Buvo:
for(<>){$a=0;$_||next;$a+=$_--while!/-/&&$_;print"$a\n"}
Yra:
$_&&print$_*=$_++/2,"\n"for<>
29 vs 21 (jau neitin blogai)

Paskutinią savaitę šiek tiek pavarčiau, paskaičiau Perl golfo literatūros: pradmenų ir istorijos. Įdomu.

2013 m. gruodžio 12 d., ketvirtadienis

Pusmečio apžvalga (2013 rudens semestras)

Šį semestrą teko nieko nesimokyt iš universitetinių dalykų. Buvo keli susiję su programavimu. Naudingi.

---

Laisvalaikiu tekdavo lankytis pas Codeforce'us. Mano kelnių juostelės nuspalvintos pilka spalva - toks tėra "veiklos" ir lygio įvertinimas.
Čia išsprendžiau aibelę uždavinių. Vienam uždaviniui trunka daugmaž pusvalandis ar daugiau laiko. Pagrinde Perl'o kalba, arba rečiau Pascal'iu - kuomet prireikia dvimačių masyvų, arba greičio.
Išsprendus vieną uždavinį su tapačios logikos kodu, Perl'as naudojo beveik limitą - 2 sekundes, o Pascal'is - deklaruota kaip 30 ms.
Laikui (2h) spręsti teko, ir dažniausiai - nesėkmingai. Paskutiniame ture patiko išspręsti 2 ir 3 užduotis preliminariai. Net nudžiugau, ir ėmiau skaityti penktąją (sudėtingiausiąją, bet lengviau atrodžiusią negu ketvirtoji). Tačiau laikui sumažėjus, išsprendžiau pirmąją. Rinkausi mėgint strategiją - spręsti ne nuo pirmo uždavinio, taupant taškus. Ir pradžia buvo gera - antrąjį išsprendžiau neįtikėtinai greit (kaip man) - per <20 min. Pasibaigus turnyrui, 2 ir 3 užduotis man nulaužė sudėtingesni testai - klaida ir time-limitas. Tai vėl nusiritau taškuose. Neblogai.

OpenCup daug rečiau sudalyvauju. Panašaus lygio sėkmė lydi.
Truputį pažaidžiau golf'ą. Turbūt kojom žaidžiau ar kuo? :D ...kad visai netrumpi atsakymai išeina.

Vieną vakarą pasimokiau (prisiminiau) Perl'o regexp'ų, pagrindų. Viena įdomesnių sričių ir dar logikos reikalauja. Buvo svajonė ("sportinė") išmokt nesudėtingus uždavinukus vienu regexp'u spręst...

Daugiau lyg nieko.

2013 m. rugpjūčio 13 d., antradienis

Programa išplečianti kodo santrumpas

Kažkada svajojau apie tokią programą, kuri leistu rašant Pascal'iu, naudoti santrumpas (pvz. "++A", vietoje "A:=A+1" ar "inc(A)"), bei leistų vietoje "begin" ir "end", rašyti "{" ir "}", kas užima mažiau vietos, ir yra paplitę C kalbų šeimoje.
Taigi, pamėginau su Perlu parašyti programą, kuri redaguoja tekstą: "sutrumpintą" Pascal programos kodą verčia tikru kodu. Įvykdžiau tik keletą savo paties pageidavimų, jie yra tokie:

{ / } => begin / end,
++/-- A => inc(A) / dec(A),
A+=B => A:=A+B,
A-=B => A:=A-B,
A%=B => A:=A mod B,
A//=B => A:=A div B,
A&=B => A:=A and B,
A|=B => A:=A or B,
A!>B => if A>B then A:=B (patogi santrumpa),
A**B => A*A*A*...{B kartų} (o ką? :D)

fu I N { => for I:=1 to N do {
fd I N { => for I:=1 downto N do { (ups, nelogiška...)
(fu - for up, fd - for down),

ir kt.

Jau keletą kartų pasinaudojau, patiko.
Tik, žinoma, programos galvojimas dažnai užima daug daugiau laiko, negu pats kodo rinkimas, todėl programa parašyta be sportinio tikslo, bet iš įdomumo.

Ir programa realizuota menkokai: nenaudoju asociatyviųjų masyvų, silpnos ir galimai lėtos reguliariosios išraiškos, prastokas kodavimo stilius, neaiškūs kintamųjų vardai.

Kodas:
( http://ideone.com/2RJkeM )

$_=join"",<>;

print "(*\nModified from: \n\n", $_, "\n*)\n\n";

s/\blint\b/longint/gm;
s/\bint\b/integer/gm;
s/\bstr\b/string/gm;
s/\bbool\b/boolean/gm;
s/\bwln\b/writeln/gm;
s/\brln\b/readln/gm;

/{/m;

$s=$`; $t=$';

$s=~s#([=:])([^=:;]*?),\s*(\b\w+\b)\s*;#
    ($m1=$1,$m2=$2,$m3=$3) and
    (@m=$m2=~s/\s*(\w+)\s*/1..$1/g) and
    $m1."array [".$m2."] of ".$m3.";"
    #gme;

$t=~s/([+-])\1\s*([a-z][\w\[\],]*)/($1 eq "+"?"in":"de")."c($2)"/gemi;
$t=~s/([a-z][\w\[\],]*)\s*([+-])=\s*(\w[\w\[\],]*)/"$1:=$1".($2 eq "+"?"+":"-")."$3"/gemi;
#  $t=~s/([a-z][\w\[\],]*)\s*(\*|\/)=\s*(\w[\w\[\],]*)/"$1:=$1".($2 eq "*"?"*":"/")."$3"/gemi;
$t=~s/([a-z][\w\[\],]*)\s*([&|])=\s*(\w[\w\[\],]*)/"$1:=$1".($2 eq "&"?" and ":" or ")."$3"/gemi;
$t=~s/([a-z][\w\[\],]*)\s*(\%|\/\/)=\s*(\w[\w\[\],]*)/"$1:=$1".($2 eq "%"?" mod ":" div ")."$3"/gemi;

$t=~s/([a-z][\w\[\],]*)\s*!([><])\s*(\w[\w\[\],]*)/if $1$2$3 then $1:=$3/gmi;

$t=~s#f([ud])\s*(.*?)\s*{#
    (($m0=$1 eq "u"?"":"down"),$m=$2) and (@m=$m=~s/,/ /g) and (@m=$m=~s/ +/ /g) and
    "for ".(
    $m=~/ (\S)+ /?("$`:=$1 ".$m0."to $'"):
    ($m=~/ / and "$`:=1 ".$m0."to $'")
    )." do {"
    #gemi;
   
$t=~s#rot\s*\(?([^;}]+)\)?\s*([;}])#
    ($m1=$1, $m2=$2, $m1=~s/[^,]+//emi, $t1=$&, $t1=~s/\s//g, $t11="$t1:=", $m1=~s/,\s*(\w+)\s*/
        (1, $t11.="$1; $1:=")
        /gemi, $t11.="$t1"."$m2") and ($t11)
    #gemi;
   
$t=~s/([a-z][\w\[\],]*)\s*\*{2}\s*(\d+)/"$1".("*$1"x($2-1))/gemi;
   
$t=~s/{/ begin /gm;
$t=~s/}/ end /gm;

$_=$s." begin ".$t;

# s/ +/ /gm;
# s/^ | $//gm;

print;






Kartu plačiau paaiškinsiu (išskaidysiu) kurią nors kodo eilutę, pvz. 44-ą: 

"$t=~s/([a-z][\w\[\],]*)\s*\*{2}\s*(\d+)/"$1".("*$1"x($2-1))/gemi;

"$t" yra teksto dalis (čia išsaugota visas kodas einantis po pirmojo begin'o ("{")).
Šiai teksto daliai darome keitimus, naudojant konstrukciją: "$t=~s///".
Gale prirašyti modifikatoriai: g, e, m, i. Reiškias: "global", "evaluate", "multi-line", "ignore case". Reiškias: 1) modifikuos visas (o ne vieną) surastas ieškomas eilutės vietas, 2) apskaičiuos, ką reikia įrašyti vietoje surastų ieškomų eilutės vietų, 3) tekstą įsivaizduos kaip vieną didelę eilutę, suklijuotą eilutės pabaigos ženklais, 4) ieškos bet kokių (mažųjų ir didžiųjų) raidžių.
Ką ieško?
Ieško to, kas yra "$t=~s/čia//".

Į ką keičia?
Į tą, ką apskaičiuos "$t=~s//šičia/".
Ieško štai ko:
dviejų iš eilės pasikartojančių žvaigždučių (daugybos ženklų) - "\*{2}", po kurių gali sekti įvairūs tarpai "\s*" ir tada - seka skaičius - "\d+". Surastą skaičių mes išsisaugojame, nes apskčiaudžiame - "(\d+)". Prieš pasikartojančias žvaigždutes, gali būti tarpų - vėl "\s*", o prieš juos privalo būti kintamasis, kuris prasideda lotyniška raide (didžiąja ar mažąja), o tolimesni jo simboliai (jeigu yra) privalo būti iš tokios simbolių aibės: "a-z" + "0-9" + "_" + "[" + "]" + ",". Kintamojo pavyzdys - "mas1[3,j]". Kintamasis, kurio (deja) paieška nesuras - "mas1[i+1,j]".
Keičia į štai ką:
surastą ir į kintamąjį "$1" išsaugotą kintąmąjį, po kurio seka "$2" (surastą skaičių) kartų (minus vienas) pasikartojantis užrašas "*$1" (daugybos ženklas ir kintamasis).

2013 m. liepos 22 d., pirmadienis

Pusmečio apžvalga (2013 pirmoji pusė)

Šį semestrą universitete teko pasimokyti nedaug dalykų. Tačiau buvo ir tokių, kuriuose reikėjo programuoti.
Viename dalyke reikėjo naudotis žiniomis iš kokių dešimties anksčiau praeitų dalykų, ir daugiausia programuoti Perl kalba. Taip pat reikėjo naudotis R kalba, bei grafikos programomis...
Kitame dalyke reikėjo suprogramuoti grafą apdorojantį algoritmą. Programa turėjo surasti ir išvesti atstumus tarp grafo taškų.
Gavosi taip, kad praktiškai nepasimokiau abiejų dalykų, ir neparašiau daugumos programų. Priežastys kažkur anapus. O universitetas tikrai patiko.

***

Savaitgaliais teko, jau nebijau pavadint - tradiciškai, dalyvauti OpenCup'e. Bet tik ankstyvo žiemsario turuose. Prie manęs į komandą prisijungė jaunas protas. Deja matematiškas, funkcinės mąstysenos garbintojas, dievinantis Python'o kosmines funkcines galimybes ir dar net nežinojęs kaip šioje kalboje nuskaityti duomenis iš failo ar standartinės įvesties (stdin) :) .
Sekėsi mūsų komandai prastokai, bet man vistiek ji patiko. Aš imdavausi spręsti lengviausius ir suprantamiausius, bei trumpiausių sąlygų uždavinius, o linksmasis ir kupinas optimizmo komandos draugas - pačius sunkiausius ir labiausiai matematiškus uždavinius. Nei jam, nei man nepavykdavo išspręsti savų uždavinių, nors gal kokį lengvesnį ir buvau išsprendęs. Mėginau Perlu ir kartą - Rubiu.

Po to laisvalaikiais užsikabinau dalyvauti (kaip šios srities liaudis vadina - "pakibinėti") Codeforces turnyrėliuose. Sudalyvavau iš viso 12-oje.
Patiko dalyvauti. Nors sekdavosi sunkiai. Viską rašiau Perlu. Po 12-os turnyrėlių antrąjį kartą nusileidau į labai žemą reitingą (esu "Newbie") - tas mano reitingas yra pats žemiausias iš visų apie trisdešimties registruotų svetainėje lietuviškų akauntų. Nesistebiu, nes programuoju labai silpnai ir lėtai. Lėtai sekasi koduoti, ir susikaupti. Daug klaidų ir neteisinga metodika. Sprendžiu uždavinius sudėtingėjimo eiliškumu.

Labai patiko paskutinio turo trečias uždavinys. Jį išsprendžiau tik šįryt. Pasirodo, jį išsprendę tik ~700 Codeforces vartotojų. Reiškia, kad išsprendžiau ne lengvą, bet "vidutinį" uždavinį - tai džiugina. Tačiau deja išspręsti per varžybų laiką nepavyko.

Uždavinys toks, kad:
pateiktas simboliais "." ir "E" užpildytas kvadratas.
Reikia nurodyti minimaliausią kiekį koordinačių porų (bet kurių tinkamų), kurių kiekviena reiškia kvadrato vietą, kurioje yra taškas, ir nuo kurios į visas keturias puses esantys langeliai ir pats langelis "užmigdomi". Ir visos koordinačių poros "užmigdo" visą kvadratą. Antraip išvesti "-1". 329A.

Problema, kad uždavinį išsprendžiau mintyse neteisingai, ir tokį pradėjau programuoti. Suprogramavau. Tačiau testų nepraėjo. Vėliau supratau, kad ne apie visus atvejus pagalvojau, ir dar kartą išsprendžiau, bet ir vėl neteisingai - vėl ne apie visus atvejus buvo pagalvota. Šįkart jau buvo lengviau, nes pasibaigus turnyrui - galėjau matyti, kokių testinių atvejų programa nepraeina, iš jų supratau, kad nors ir suprogramavau teisingai, bet ne visai tokį uždavinį. T.y. aš jo teisingai neišsprendžiau. Kai supratau, kaip yra teisingai, tada ir suprogramavau taip, bei sprendimas buvo užskaitytas. Kartais būna, kad pilnai išspręstas visiems atvejams uždavinys lengviau suprogramuojamas, negu neteisingai išspręstas (ne visiems pastebėtiems atvejams), o kartais - sunkiau. Šįkart teisingas sprendimas buvo lengviau suprogramuojamas, negu neteisingas. Jeigu būčiau jį sugalvojęs tik ką susipažinęs su uždaviniu, tuomet gal net spėčiau jį atlikti per turnyrinį laiką (likusias ~1,5 val.). Uždavinys grakštus.
Uždaviniui išspręsti, man reikėjo pasirašyti procedūrą, kuri transponuoja mano simbolių kvadratą. Ši procedūra (subrutina) pasirašė per ~1/3 laiko, naudoto spręsti teisingai sprendžiamą užduotį.
Tačiau teko gyvenime jau keletą sykių rašyti atskirą transponavimo užduotį (porą kart - golfe, kartą - opencup'e). Dėl to, ją rašiau greičiau. Tačiau, juk galėčiau pačią subrutiną naudoti kiekvienam kode, kad nereikėtų per naują rašyti to paties. Bet neaišku, ar taip daryti verta.


Bendrai paėmus, programavimu ir tobulėjimu jo srityje skurdus gavosi pusmetis.

2013 m. vasario 16 d., šeštadienis

Anarchy golfas - 2

Anarchy golf puslapyje daugiausia žaidžiau su Perl kalba, bet kelis kartus pamėginau ir su FPC, bei su Ruby.
Svetainė tikrai anarchiška, nes net pats pasirodo, galiu joje kurti užduotis. Prieš mėnesį tą ir pradėjau išmėginti.
Sukūriau dvi [1, 2] užduotėles, kurios sulaukė normalaus populiarumo, ir vieną - kuri itin nepopuliari, reiškia - nepatikusi [3].

***
Dar įkelsiu keletą neitin prasmingų mano pasispardymų:

1. Užduotis "alternating case lines": kas antra eilutė verčiama aperkeisu pradedant pirmąja, kitos - lavuerkeisu. Taip kito kodas:



print++$i%2?uc:lc for<>

O štai taip atrodo geriausias sprendimas (žavu!):
print uc,lc<>while<>    # autorius: tanon



2. Užduotis "repeated number". Taip kito kodas:


print((chop||next)x$_,"\n")for 21..89

Ta pati užduotis kaip sekėsi su Ruby:

(21..89).each{|i|i%10!=0&&puts((i%10).to_s*(i/10))}

2013 m. vasario 2 d., šeštadienis

Pusmečio (2012 rudens semestro) apžvalga

Šio semestro medžiaga (dalykai) universitete labai patiko. Kai kurių dalykų net teko anksčiau ar vėliau pasimokyti. Kai kurių ne.

Buvo galimybė mokytis kompiuterinių tinklų. Šį praskipinau.

Ganėtinai stipriai patiko, bei manau, kad buvo man naudingas, dalykas apie naudojimąsi Unix terpe, komandine eilute, rašyti kažkokius skriptukus, naudotis "mikrokalbomis" (awk, sed berods). Dar tame dalyke teko pasimokyti dirbti su Subversija (svn). Bei kurti Makefailus, bei juos naudoti kuriamos programos testavimui, iš kart naudojant keletą testinių failų.
Anksčiau (ir dabar) programas rašydavau taip, kad turėdavau daug jos kopijų, ir versijų. Taip pat retai rašydavau įrašus (log'us) naujoms versijoms, dėl to po kiek laiko atsivertęs - pasimesdavau - kuo viena nuo kitos skiriasi. Beigi būdavo įvairių versijų atšakų. Susipažinimas su SVN buvo naudingas - teko juo naudotis, tačiau "revert'inti" programas teko retai, ir atsikėlinėt senesnes versijas - irgi teko retai.
Subversija veikia taip: yra kažkur nutolęs serveris, kuriame yra sukurta repozitorija. Internetu bendraujama su ta repozitorija, ir į ją "įdedama" saugojimui rašoma programa. Kiti, turintys priėjimą, gali tą programą atsisiųsti ir naudoti, ar net patys ją keisti, plėsti, išsaugoti. Taip sukuriama galimybė nuotoliniam bendradarbiavimui. Tokio išbandyti neteko. Ciklas toks: iš repozitorijos atsisiunčiama programa (jos kopija), ji modifikuojama, ir vėliau commit'inama (nusiunčiama atgal). Kitą kartą vėl ji bus atsisiunčiama (checkout'inama), modifikuojama, commit'inama. Ne tik programa, bet apskritai bet kurie failai ar folderiai. O jeigu norėsis atsisiųsti senesnę failo versiją, tai reikės tiesiog įvesti senesnės revizijos (commit'inimo) numerį (komanda: svn update -r N; N- numeris). Kiekvieną kart commit'inant, SVN'as prašo įvesti log'ą - parašyt, kas naujo prisidėjo naujoje revizijoje, ar kas buvo pakeist, kad po to būtų lengvaiu atsekti. 

Daugiau konkrečiai programavimo dalykų nebuvo, tačiau buvo susijusių dalykų.

Viename buvo mokomasi statistikos ir įvairių testų, bei tam buvo naudojamas MĖ Excelis, bei mokomasi ir naudojamasi R programavimo kalba. Duomenų generavimui, apdorojimui ir atvaizdavimui. Neteko išmokt. O pats R'as patiko. Ir nemokamas, ir gana draugiškas, ir daug modulių jam sukurta.

Kitame teko mokytis visokių kodavimų, ir bereikėjo parašyti kelias programas, kurios atlieka kodavimą ir dekodavimą. Rašiau jas "de novo", bet pačių kodavimo algoritmų gerai neišmaniau, tad naudojausi Wikipedija ir internetais, kad pagal algoritmų iliustruoto veikimo pavyzdžius, parašyčiau programas. Naudojau Perl kalbą. Pavyko parašyti su klaidom, ir neefektyviais algoritmais, bet patiko bent tiek, kiek pavyko.

Dar viename dalyke buvo visokių mokymųsi naudotis jau sukurtomis ir plačiai naudojamomis programomis... Be to reikėjo parašyti ir patiems įvairių užklausų. Tai šitą irgi beveik nepasimokiau.

*****

Be mokomųjų dalykų, sekmadieniais teko dalyvauti OpenCup varžybose (contest'uose), fakultete ar iš namų. Dalyvavau rečiau negu pavasarį. Buvau šį kart vienas komandoje. Tai, kadangi vienas ir nekoks programuotojas, tai isšpresdavau vos po ~1 uždavinį per etapą - nedaug. Kai kada ne visas 5 valandas dalyvaudavau, o kaip išeidavo.
Nespėdavau įsigilinti ar net perskaityti visų sąlygų. Imdavau lengvesniuosius uždavinius. Kelis teko spręsti Pascal'iu, tačiau jau šį semestrą ėmiau naudotis ir Perl'u. Ypač padėjo ten, kur reikėjo apdoroti eilutes.
[Papildau keliais uždavinių sprendimais (įkeliu į Ideone.com svetainę).
* Su išsamesniu kodo pakomentavimu,
* karalium nueit iš vieno langelio į kitą,
* chupakabros eina į vieną pusę, barmolėjai į kitą, ir valgo mažesnius berods (-1 yra tuščias laukas),
apskaičiuoti kiek kurių liks,
* ištrinti bug'ų "žymes" iš kodo (perl'o regexp'ų žavumas)]

Pusmečiui įpusėjus, šiek tiek susidomėjau (gana primityviai) golf'ingu, ir gruodžio-sausio mėn. ėmiau žaisti golf'ą. Rezultatai neįpatingi, bet retkarčiais tiesiog būna įdomu.
O iškart po sesijos - atostoginę savaitę kiek daugiau užsiimiau laiko praleidimu prie programų. Tai buvo golfingas (Perlu), Ruby kalbos pagrindų mokymasis, ir contest'inių programavimo užduočių sprendimas. Contestin'es užduotis pasprendžiau pačias lengviausias, užsiregistravęs į Codeforces ir Timus OJ.
Codeforces labai patiko - viskas puikiai paruošta turnyrui, kurio formatas gana žaismingas. Taip pat neturnyro metu galima žiūrėti dalyvių kodus - kaip jie sprendžia kokias užduotis, kur klysta.