Kirjautuminen

Haku

Tehtävät

Keskustelu: Yleinen keskustelu: Datatähti 2012

Sivun loppuun

Antti Laaksonen [18.10.2011 14:23:35]

#

Datatähti 2012 -kilpailu alkaa tänään:

http://users.utu.fi/knuutila/datatahti/

Kilpailuun voivat osallistua peruskoulun ja lukion oppilaat. Alkukilpailu on 18.10.–1.11.2011, ja sen perusteella valitaan osallistujat loppukilpailuun, joka pidetään Helsingin yliopistolla helmikuun alussa.

Datatähteen kannattaa ehdottomasti osallistua, jos algoritmien ohjelmointi kiinnostaa. Tervetuloa mukaan!

Grez [18.10.2011 14:37:58]

#

Mietin ensimmäisessä tehtävässä ohjelmointikielitarjonnan ja nopeustavoitteen huomioiden, että saakohan esim. C:ssä käyttää inline assemblyä? Vai pystyykö jossain kielistä laskemaan suoraan kaksi 64-bittistä lukua yhteen ja tarkistamaan yli menevän bitin prosessorin carry-flagista?

Jalmari91 [18.10.2011 18:48:49]

#

Olisi mukava osallistua, mutta kun ei saa enää. Olisi ihan kiva kun tulisi myös yliopisto-opiskelijoille samanlainen kilpailu.

-tossu- [18.10.2011 18:59:20]

#

Tämän vuoden tehtävät 1 ja 3 näyttävät pikaisesti katsottuna sellaisilta, että parhaiten niissä pärjää etsimällä netistä valmiin algoritmin.

Saa nähdä, jaksanko osallistua, tehtävät näyttävät sellaisilta, ettei niistä saa helpolla pisteitä, eikä minulla ole nykyään kovin paljoa koodausaikaa.

Hennkka [18.10.2011 20:21:15]

#

Saakos tehtävien ratkaisussa käyttää putkan koodivinkkejä?

Jaska [19.10.2011 00:36:46]

#

Toi isojen kokonaislukujen kirjasto on sinänsä outo, että lopussa voi tehdä oletuksen pituudesta mutta tirat on tehtävä ilmeisesti ilman tätä oletusta. Saakohan tuossa tehtävässä olettaa, että luvut on mahduttava keskusmuistiin vai pitääkö tarkastaa, onko koneeseen kytketty esim. muistitikkuja, joille lukujen bittejä voi tunkea jos muualle ei mahdu?

Grez [19.10.2011 00:47:06]

#

tirat on ilmeisesti tietorakenteet? Tottakai oletukena on se, että muuttujat/luokat säilötään muistissa kun niitä käytetään. Se on sitten ympäristön huoli sivuttaa jos ei mahdu fyysiseen muistiin kerralla. Toisaalta hyvä toteutus ei varaa aina esimerkiksi 10 megaa muistia jos käsiteltävä luku on 200 merkkiä pitkä.

Tietenkin on erityistilanteita, joissa halutaan käsitellä niin isoja lukuja, että ne on järkevämpää jo ohjelmassa tallentaa levylle ja huomioida levyoperaatioiden hitaus sovellusta kehitettäessä. Tästä kuitenkin olisi varmasti erillinen maininta.

Uskoisin, että ajatuksena on ollut että ohjelma käyttäisi pelkästään keskusmuistia, kun ainoastaan se on ilmoitettu (max 1. Gt).

En näe että tuossa olisi mitään ongelmaa, kun kuitenkaan lukuja ei tarvita kuin muutama kerrallaan muistissa ja maksimipituisia lukuja mahtuu yli 20 kerralla muistiin.

Itse käyttäisin dynaamisia taulukoita. Kaikissa operaatioissa lopputuloksen pituus on mahdollista helposti päätellä 1-2 yksikön tarkkuudella.

jalski [19.10.2011 08:53:32]

#

Grez kirjoitti:

Itse käyttäisin dynaamisia taulukoita. Kaikissa operaatioissa lopputuloksen pituus on mahdollista helposti päätellä 1-2 yksikön tarkkuudella.

Merkkijonojen ja desimaaliluvuilla laskennan puolelle taitaisi oma toteutukseni kallistua...

Antti Laaksonen [19.10.2011 15:22:38]

#

Jalmari91 kirjoitti:

Olisi ihan kiva kun tulisi myös yliopisto-opiskelijoille samanlainen kilpailu.

Yliopiston opiskelijoille on ainakin NCPC ja sen jatkokilpailut:

http://ncpc.idi.ntnu.no/

Hennkka kirjoitti:

Saakos tehtävien ratkaisussa käyttää putkan koodivinkkejä?

Koodin pitää olla itse tehtyä, mutta mallia saa toki ottaa.

jlaire [19.10.2011 19:36:03]

#

-tossu-: Jos ei ole muita esteitä kuin jaksaminen, kannattaa ehdottomasti osallistua. Loppukilpailuun on ainakin viime vuosina päässyt todella helposti.

Macro [21.10.2011 08:57:41]

#

Kuvittelenko vain, vai oliko 18. päivä vielä esseetehtävänä viimevuoden tehtävä liittyen kännykän käyttöjärjestelmiin?

kllp [21.10.2011 13:56:20]

#

Se oli virhe, joka on nyt jo korjattu.

Deffi [23.10.2011 14:21:57]

#

Kiusaus olisi suuri tehdä ensimmäinen tehtävä assemblyllä, sillä x86-käskykanta tukee mielivaltaisen suurilla kokonaisluvuilla laskemista sen verran hyvin.

Working with Big Numbers Using x86 Instructions

Grez kirjoitti:

Mietin ensimmäisessä tehtävässä ohjelmointikielitarjonnan ja nopeustavoitteen huomioiden, että saakohan esim. C:ssä käyttää inline assemblyä? Vai pystyykö jossain kielistä laskemaan suoraan kaksi 64-bittistä lukua yhteen ja tarkistamaan yli menevän bitin prosessorin carry-flagista?

C:ssä yhteenlaskun carry-flagin pystyy tarkistamaan purkasti näin:

tmp = a;
a += b;
carry = (a < tmp) ? 1 : 0;

Tiedä vaikka jotkut kääntäjät osaisivat optimoida tuon pelkäksi carryn tarkistukseksi, mutta en olisi niin optimistinen. Olen tällä periaatteella toteuttanut C:llä alkeellisen bigint-kirjaston, joka ei tue kertolaskua. x86:n MUL käsky tallentaa kertolaskussa ylimenevän osan EDX-rekisteriin, mutta siihen ei taida päästä C:llä käsiksi. Tietysti voi käyttää riittävän suuria tietotyyppejä, jolloin kertolasku ei vuoda yli.

Laskeskelin että noin 5 000 000 tavua riittäisi tallentamaan 10^7 merkkiä pitkiä kymmenjärjestelmän lukuja. Tilavaativuudeltaan noin puolet parempi kuin "triviaali" merkkijonoratkaisu. Yhteenlasku ja kertolasku veisivät aikaa O(n/M) missä n on taulukon pituus ja M on tietokoneen sanan pituus. Tehtävän kannalta ongelmaksi muodostuisi isojen lukujen muuttaminen oikeaan muotoon, enkä itse ainakaan keksi siihen helppoa ja tehokasta tapaa.

Grez [23.10.2011 14:49:19]

#

Eikös monet prossut muuten tue BCD-laskentaa (binary coded decimal) joten jos x86:kin tukee, niin tuollahan saisi erittäin kätevästi tehtyä mikäli jokin sallittu kieli tukisi niitä. Näin tulostminen ja lukeminen olisi huiman nopeaa verrattuna siihen että käytettäisiin normilukuja.

Ja mitä tuohon carryyn tuleen, niin mielestäni prossu myöskin osaa laskea huomioiden carryn, jolloin yhteen- ja vähennyslakussa voi vaan käydä koko sarjan putkeen yhdessä loopissa. Eli tokihan purkkailla voi, mutta jos kääntäjä ei tosiaan purkkaa "poista" niin suoritusnopeus on monta kertaa hitaampi.

jalski [23.10.2011 15:21:08]

#

Grez kirjoitti:

Eikös monet prossut muuten tue BCD-laskentaa (binary coded decimal) joten jos x86:kin tukee, niin tuollahan saisi erittäin kätevästi tehtyä mikäli jokin sallittu kieli tukisi niitä. Näin tulostminen ja lukeminen olisi huiman nopeaa verrattuna siihen että käytettäisiin normilukuja.

Kyllähän x86 on noita tukenut kivikaudelta asti. Nykyään taitaa x86:lla olla helpointa hoitaa BCD-aritmetiikka fpu:lla, mikä hoitaa homman 18-numeron tarkkuudella.

Käyttämäni PL/I-kääntäjä laskee fixed decimal laskut käyttäen fpu:ta. Oma testinä tehty isojen lukujen yhteenlasku toteutukseni laskee merkkijonoilla ja yhden loopin avulla käsitellen aina 17 numeroa + carryn jokaisella silmukan pyörähdys kerralla.

PL/I hoitaa muunnokset merkkijonojen ja lukujen välillä automaattisesti, joten tuohon tarvitaan vain jokunen rivi koodia.

Laitan tuon esille, kunhan pääsen kotiin asti. Halukkaat voivat sitten verrata oman koodinsa nopeutta PL/I-kääntäjän tuottamaan koodiin.

Pete2 [23.10.2011 15:54:03]

#

-tossu- kirjoitti:

Tämän vuoden tehtävät 1 ja 3 näyttävät pikaisesti katsottuna sellaisilta, että parhaiten niissä pärjää etsimällä netistä valmiin algoritmin.

Eikö kaikissa ohjelmointikilpailuissa pärjää parhaiten kopioimalla muiden töitä, jos ei itse osaa ohjelmoida? Jos taas osaa, niin 1 ja 3 tehtävät ratkaisee täydet pisteet saaden parissa päivässä.

-tossu- kirjoitti:

Saa nähdä, jaksanko osallistua, tehtävät näyttävät sellaisilta, ettei niistä saa helpolla pisteitä, eikä minulla ole nykyään kovin paljoa koodausaikaa.

Sama vastaus tähän: pisteitä saa hyvin jos on hyvä.

-tossu- [23.10.2011 18:31:53]

#

Pete2 kirjoitti:

Eikö kaikissa ohjelmointikilpailuissa pärjää parhaiten kopioimalla muiden töitä, jos ei itse osaa ohjelmoida? Jos taas osaa, niin 1 ja 3 tehtävät ratkaisee täydet pisteet saaden parissa päivässä.

Tehtävät olisi myös voitu laatia siten, ettei niihin löydä ainakaan kovin helpolla valmiita ratkaisuja. Isojen lukujen käsittelyyn on vaikka kuinka monta toteutusta, jonka kopioimalla saanee täydet pisteet. Kungigattarien asettelukin on melko tunnettu ongelma, johon löytynee valmis algoritmi.

Jalmari91 [23.10.2011 19:05:05]

#

-tossu- kirjoitti:

Pete2 kirjoitti:

Eikö kaikissa ohjelmointikilpailuissa pärjää parhaiten kopioimalla muiden töitä, jos ei itse osaa ohjelmoida? Jos taas osaa, niin 1 ja 3 tehtävät ratkaisee täydet pisteet saaden parissa päivässä.

Tehtävät olisi myös voitu laatia siten, ettei niihin löydä ainakaan kovin helpolla valmiita ratkaisuja. Isojen lukujen käsittelyyn on vaikka kuinka monta toteutusta, jonka kopioimalla saanee täydet pisteet. Kungigattarien asettelukin on melko tunnettu ongelma, johon löytynee valmis algoritmi.

Eihän tuosta ensimmäisestä tehtävästä voi saada täysiä pisteitä muut kuin paras ;D

-tossu- [23.10.2011 19:15:07]

#

Jalmari91 kirjoitti:

Eihän tuosta ensimmäisestä tehtävästä voi saada täysiä pisteitä muut kuin paras ;D

Ei näköjään voikaan, mutta valmis BigInt-kirjasto, jota on hyvät koodarit optimoineet ajan kanssa, lienee silti nopeampi kuin kenenkään osallistujan toteutus.

Pete2 [23.10.2011 20:38:12]

#

Jalmari91 kirjoitti:

Eihän tuosta ensimmäisestä tehtävästä voi saada täysiä pisteitä muut kuin paras ;D

Ennemminkin muut kuin parhaat.

Datatahti Ohjeet kirjoitti:

Laskennan nopeudesta saa pisteitä siten, että nopein toimitettu kilpailuvastaus saa 40p, hitain 1p ja muut vastaukset nopeutensa mukaan tältä väliltä.

Voidaan todeta, että väli on suljettu, koska muuten pisteytys ei olisi yksiselitteisesti määritelty kahden kilpailijan lähettäessä yhtä nopeat ohjelmat. On siis tietenkin mahdollista, että saman algoritmin kopioineet saavat molemmat täydet pisteet ( sikäli kun heitä ei diskata ).

jalski [23.10.2011 23:32:39]

#

jalski kirjoitti:

Laitan tuon esille, kunhan pääsen kotiin asti. Halukkaat voivat sitten verrata oman koodinsa nopeutta PL/I-kääntäjän tuottamaan koodiin.

Tuossa olisi PL/I toteutus isojen kokonaislukujen yhteenlaskua varten. Ottaa parametrikseen tekstitiedoston, jossa pitäisi olla pari numeroista koostuvaa riviä päätettynä rivinvaihdolla. Nuo lasketaan yhteen ja tulos kirjoitetaan ruudulle.

/**********************************************************************/
/* Takes input file as a parameter and reads two records from it.     */
/* These two records containing big integers are then added together  */
/* and the result is displayed.                                       */
/**********************************************************************/
testi: proc(parm) options(main);
   dcl parm char(*) varying;
   dcl infile file record input env(TEXT);
   dcl (l1, l2) fixed dec(17);
   dcl carry fixed dec(1) initial(0);
   dcl sum pic '999999999999999999';
   dcl (luku1, luku2) char(32000) varying;
   dcl zeros char(17) initial((17) '0');
   dcl result char(32000) varying;
   dcl (i, j, k) fixed bin(31);

   dcl (substr, length, verify) builtin;

   on undefinedfile(infile) goto no_inputfile;
   on endfile(infile) goto eof;
   on record(infile) goto conv_err;

   open file(infile) title(parm);
   read file(infile) into(luku1);
   if verify(luku1, '1234567890') > 0 then signal record(infile);
   read file(infile) into(luku2);
   if verify(luku2, '1234567890') > 0 then signal record(infile);

   j = length(luku1);
   k = length(luku2);

   if j > k then do;
     i = mod(j, 17);
     if i ^= 0 then luku1 = substr(zeros, 1, 17 - i) || luku1;
     j = length(luku1);
     luku2 = substr(zeros, 1, j - k) || luku2;
   end;
   else do;
     i = mod(k, 17);
     if i ^= 0 then luku2 = substr(zeros, 1, 17 - i) || luku2;
     k = length(luku2);
     luku1 = substr(zeros, 1, k - j) || luku1;
   end;

   do i = length(luku1) to 1 by -17;
     l1 = substr(luku1, i - 16, 17);
     l2 = substr(luku2, i - 16, 17);
     sum = l1 + l2 + carry;
     carry = substr(sum, 1, 1);
     result = substr(sum, 2, 17) || result;
   end;

   result = substr(sum, 1, 1) || result;

   result = substr(result, verify(result, '0'), length(result) - verify(result, '0') + 1);

   put skip(2) list(result);

   goto eof;

 no_inputfile:
   put skip list ('No input file given....');
   stop;

 conv_err:
   put skip list ('Records should be integer numbers and terminated with CRLF on OS/2 or LF on Linux.');

 eof:
   close file(infile);

end testi;

jlaire [25.10.2011 17:12:51]

#

Pete2 kirjoitti:

Eikö kaikissa ohjelmointikilpailuissa pärjää parhaiten kopioimalla muiden töitä, jos ei itse osaa ohjelmoida?

Ainakaan Datatähden loppukilpailussa ja lukiotason kansainvälisissä kilpailuissa ei pärjää kopioimalla, koska nettiä ei saa käyttää. Tässä alkukilpailussa kyse ei välttämättä ole siitä, osaisiko tehtävät ratkaista itse, vaan siitä että haluaako käyttää aikaa pyörän keksimiseen. Hyvillä ohjelmoijilla saattaa olla parempaakin tekemistä.

Toisaalta kilpailuissa joutuu kuitenkin toteuttamaan samoja tunnettuja algoritmejä yhä uudestaan ja uudestaan, joten itsenäinen ratkaiseminen on hyvää harjoitusta.

Grez [25.10.2011 17:25:21]

#

jlaire kirjoitti:

Ainakaan Datatähden loppukilpailussa ja lukiotason kansainvälisissä kilpailuissa ei pärjää kopioimalla, koska nettiä ei saa käyttää.

Mitäs materiaalia siellä muuten on käytettävissä? Itse käyttämissä kehitystyökaluissa kirjastojen dokumentaatiokin on netissä, joten mitä materiaalia siellä sitten mahtaa koneella olla. Toisaaltahan nuo tehtävät on usein sellaisia, että ihan perustoimintoja kummallisemmille jutuille ei ole tarvetta.

jlaire [25.10.2011 17:36:01]

#

Kilpailukoneille on ladattu cppreference.com tai joku vastaava sivusto, jota saa selata lokaalisti. Kerran se oli SGI:n STL-opas. Käyttiksenä oli aina Linux ja käytin monesti man-pageja kun tarvitsin tietoa C:n standardikirjastoista. Jonkin sortin C++-opas pdf:nä löytyi ainakin pari kertaa työpöydältä, mutta ei sellaisen lukemiseen ole aikaa.

Pascalille jotain vastaavaa.

Metabolix [25.10.2011 17:38:08]

#

jlaire kirjoitti:

Tässä alkukilpailussa kyse ei välttämättä ole siitä, osaisiko tehtävät ratkaista itse, vaan siitä että haluaako käyttää aikaa pyörän keksimiseen.

Viimeaikaisen loppukilpailutason perusteella epäilen kyllä aivan muuta. Tosin kai huonompikin koodari saa sentään kahdessa viikossa jotain aikaan.

Olisi jännä tietää, minkä verran pisteitä BigInt-tehtävästä saisi pelkällä long-tyypillä (tai long double -tyypillä).

Lukemisen ja tulostamisen voi Grezin esittämässä ratkaisussa saada varsin nopeaksi myös tavalla, joka ei edellytä BCD-operaatioita: voi käyttää 32-bittisten arvojen sijaan 9-numeroisia arvoja. Tuskinpa ohjelman suoritusaika kuitenkaan jää tulostuksesta kiinni muillakaan järkevillä toteutustavoilla.

Grez kirjoitti:

Mitäs materiaalia siellä muuten on käytettävissä?

Yleensä tehtävät ovat luonteeltaan sellaisia, ettei kehitysympäristön dokumentaatiolla ole paljonkaan väliä. Enintään joutuu C++:n kanssa vähän arpomaan, oliko tietyssä STL-luokassa nyt insert, push vai push_back. Jos STL:n sisältö ei ole ennestään tuttu, tuskin sitä ehtii kilpailutilanteessa ruveta opettelemaan.

Grez [25.10.2011 18:15:33]

#

Metabolix kirjoitti:

Lukemisen ja tulostamisen voi Grezin esittämässä ratkaisussa saada varsin nopeaksi myös tavalla, joka ei edellytä BCD-operaatioita: voi käyttää 32-bittisten arvojen sijaan 9-numeroisia arvoja. Tuskinpa ohjelman suoritusaika kuitenkaan jää tulostuksesta kiinni muillakaan järkevillä toteutustavoilla.

Juu, pohdintani koskikin ihan puhtaasti sitä mahdollisuutta, että olisi voinut tehdä esim. yhteenlaskuloopin konekielellä, jolloin olisi voinut vaan loopissa ajaa ADD-komentoa ilman minkäänlaista tutkimista tai branchaysta. Tietenkin jos kirjoittaa esim. C:llä, jossa Carry-flagia ja muita rekistereitä ei voi hyödyntää, niin silloin ei ole järkevää miettiä BCD:tä.

Grez kirjoitti:

Enintään joutuu C++:n kanssa vähän arpomaan, oliko tietyssä STL-luokassa nyt insert, push vai push_back. Jos STL:n sisältö ei ole ennestään tuttu, tuskin sitä ehtii kilpailutilanteessa ruveta opettelemaan.

No itse en ole hirveästi ulkoa opetellut pitkään aikaan mitään. Sielläkin varmaan on käytössä IDE:t, jotka tarjoilee oikeat kirjotusmuodot ja eri parametrivaihtoehdot. Mutta jos näin ei olisi niin sitten voisi kyllä silloin tällöin kaivata dokkareita. Joskus joissain huonoissa systeemeissä on myös sellaisia parametreja, joista ei voi olla varma halutaanko siinä vaikka aika sekunteina vai millisekunteina, niin sekin olisi hyvä pystyä tarkistamaan. Olipas huono esimerkki.

Ja tosiaan kuten molemmat totesimmekin, tehtävien luonteesta johtuen tuskin hirveän monimutkaista kirjaston käyttöä tarvitaan.

Cybeet [04.11.2011 09:03:14]

#

Olisin halunnut tänä vuonna päästä osallistumaan Datatähteen, mutta taaskaan en ollut vielä jaksanut opetella ohjelmointia niin hyvin että edes viitsisin osallistua. :< Pitänee katsoa ensi vuonna uudestaan...


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta