Autorské riešenie
[stiahni imp : py]

  • Počet riešiteľov: 25 / 37 = 68 %

  • Úspešnosť riešenia: 3,5 / 6 = 0,58%

Cieľom tejto úlohy je graficky znázorniť ľubovoľné celé číslo podľa pravidiel uvedených v zadaní a teda postupne:

  • Každú cifru čísla znázorniť vodorovnou modrou čiarou dlhou cifra*10 a hrubou 10.

  • Modrú čiaru nakresliť na sivú čiaru rovnakej hrúbky, ale vždy dĺžky 100.

  • Viaccifernému číslu kresliť znázornené cifry za radom pod seba zhora nadol.

  • Ak je číslo kladné, modrú čiaru zarovnať k ľavému okraju sivej čiary, ak je záporné, tak k pravému.

na obrázku je ukážka grafického znázorňovania čísel na číslach -149052 a 8712

Čo je potrebné spraviť, aby sme splnili každú z týchto 4 podmienok? Číslo, ktorí chceme znázorniť je parametrom funkcie. Potrebujeme zistiť, či je kladné, záporné alebo 0, aby sme vedeli, ku ktorej strane sivej čiary treba zarovnávať modré čiary. Keď to už vieme, môžeme ďalej pracovať len s absolútnou hodnotou tohto čísla a postupne znázorňovať jeho cifry. To, aby sa čiary znázorňujúce cifry čísla nakreslili všetky a v správnom poradí pod seba, je asi najzložitejšou časťou tejto úlohy. Je možných viacero prístupov. Prvým je oddeľovanie poslednej cifry pomocou príkazov mod a div (zvyšok po celočíslenom delení a celočíselné delenie) a kreslenie cifer zdola nahor. Ďalším je prechádzanie čísla ako stringu postupne po znakoch a kreslenie zhora nadol. To je potrebné spraviť pre všetky cifry, teda potrebujeme počítadlo cifier.

Keďže všetky čiary, ktoré budeme kresliť, sú hrubé 10, už v úvode použijeme príkaz nechhp 10 (resp. pero.pensize(10).

Na kreslenie čiary použijeme pomocnú procedúru ciara s parametrami dlzka a smeruje, ktorá sa otočí smerom smeruje, nakreslí čiaru dĺžky dlzka, vráti sa naspäť a otočí sa do pôvodného smeru. Túto pomocnú procedúru využijeme pri kreslení modrej aj sivej čiary.

Aby sme zistili, či je číslo kladné alebo záporné (alebo 0), použijeme príkaz ak2 :cislo >= 0 (resp. if cislo>= 0). Ak táto podmienka platí, chceme otočiť korytnačku vpravo o 90°, aby kreslila čiaru zľava do prava a v podstate zarovnala modrú čiaru k ľavému okraju sivej čiary, a teda premennú smeruje nastavíme na 90. Ak táto podmienka neplatí, chceme otočiť korytnačku vľavo o 90°, čo je zároveň vpravo o -90°, aby kreslila čiaru opačne, sprava do ľava a teda premennú smeruje nastavíme na -90, aby sme na otáčanie korytnačky používali stále len jeden príkaz. Následne môžeme v premennej cislo uchovávať už len jej absolútnu hodnotu.

Ďalej už potrebujeme znázorniť každú cifru čísla osobitne. Použijeme na to prvý z dvoch vyššie spomínaných prístupov a teda postupné oddeľovanie cifier od konca. Kým má číslo aspoň jednu cifru, tak do premennej poslednaCifra (resp. posledna_cifra) vložíme jeho poslednú cifru príkazom urobTu "poslednaCifra mod :cislo 10 (resp. posledna_cifra = cislo % 10) a následne túto cifru znázorníme.

Teda kým je číslo > 0, budeme opakovať tento postup. Avšak nesmieme zabudnúť na špeciálny prípad a to keď je znázorňované číslo práve číslo 0. To je jediný prípad, kedy neplatí, že číslo > 0, ale počet cifier ostal nezmanený, teda 0. Na to použijeme príkaz s kombinovanou podmienkou kym [alebo :cislo >0 :pocetCifier=0], (resp. while cislo > 0 or pocet_cifier==0: ).

Ako znázorneniť cifru? Najprv nakreslíme sivú čiaru, nastavíme farbu pera na sivú a pomocnej procedúre ciara zadáme parametre 100 a premennú smeruje. Následne nakreslíme modrú čiaru, nastavíme farbu pera na modrú a pomocnej procedúre ciara zadáme parametre poslednaCifra*10 (resp. posledna_cifra*10) a premennú smeruje. Aby sme nasledujúcu cifru mohli kresliť na správne miesto, zdvihneme pero a posunieme korytnačku o 13 krokov vpred.

Túto poslednú cifru potrebujeme z čísla odstrániť. Dá sa to urobiť napríklad tak, že cislo celočíselne vydelíme číslom 10 príkazom urobTu "cislo div :cislo 10 (resp. cislo = cislo // 10 ) a ešte potrebujeme zvýšiť počítadlo počtu cifier o 1, t.j. urobTu "pocetCifier :pocetCifier+1 (resp. pocet_cifier = pocet_cifier+1).

Na úplný záver je ešte potrebné vrátiť korytnačku naspäť na pôvodné miesto a do pôvodného smeru. Keďže smer sme si stále zachovávali, nepotrebujeme ho viac meniť. Ale posunuli sme sa vpred o 13 krokov pre každú cifru, teda o 13*pocetCifier (resp. 13* pocet_cifier), preto je potrebné spraviť toľko krokov vzad.

;Imagine logo
viem ciara :dlzka :smer
  vp :smer
  do :dlzka
  do -:dlzka
  vp -:smer
koniec
    
viem grafickeCislo :cislo
  nechhp 10
  ; kladne / zaporne
  ak2 :cislo >= 0 [
    urobTu "smeruje 90
  ][
    urobTu "smeruje -90
  ]
  urobTu "cislo abs(:cislo)
  urobTu "pocetCifier 0
  kym [alebo :cislo >0 :pocetCifier=0][
    urobTu "poslednaCifra mod :cislo 10
    pd
    nechfp "siva
    ciara 100 :smeruje
    
    nechfp "modra
    ciara :poslednaCifra*10 :smeruje
    ph
    do 13
    urobTu "cislo div :cislo 10
    urobTu "pocetCifier :pocetCifier+1
  ]
  do -:pocetCifier*13
koniec
#Python
import turtle

def ciara(dlzka, smeruje):
    pero.right(smeruje)
    pero.forward(dlzka)
    pero.forward(-dlzka)
    pero.right(-smeruje)

def graficke_cislo(cislo):
    pero.pensize(10)

    # zistíme, či je číslo kladné alebo záporné,
    # aby sme vedeli, či kresliť vpravo alebo vľavo
    if cislo >= 0:
        smeruje = 90
    else:
        smeruje = -90

    cislo = abs(cislo)
    pocet_cifier = 0

    # grafické znázornenie jednotlivých cifier
    while cislo > 0 or pocet_cifier==0:
        posledna_cifra = cislo % 10
        pero.pendown()

        # pomocná sivá čiara
        pero.pencolor("gray")
        ciara(100, smeruje)


         # modrá čiara reprezentujúca konkrétnu cifru
        pero.pencolor("blue")
        ciara(posledna_cifra*10, smeruje)


        pero.penup()
        pero.forward(13)
        cislo = cislo // 10
        pocet_cifier = pocet_cifier+1
    # vrátenie sa na miesto začiatku
    pero.forward(-pocet_cifier*13)

Vaše zaujímavé riešenia a najčastejšie chyby

Túto úlohu riešilo 25 tímov, z toho 13 tímov v jazyku Imagine a 12 tímov v jazyku Python, pričom v jazyku Python bola úspešnosť vyššia o 0,09%. Celkovo hodnotíme túto úlohu za úspešnú a dobre zvládnutú.

Zaujímavé riešenie, ktoré chceme vyzdvihnúť, je riešenie tímu File-Open expert, ktorí na testovanie vhodnosti čísla použili príkaz try. Okrem toho bolo zaujímavým postupom, vyskytujúcim sa len v jazyku Python, vykresľovanie znázornení cifier zhora nadol, teda od prvej po poslednú, pomocou pretypovania vstupu na string. Niektorý tím vykresľoval dokonca najprv všetky sivé čiary a až nakiec všetky modré. Žiaľ, vyskytli sa aj 2 tímy, ktoré odovzdali neprehliadnuteľne podobné riešenia a museli byť sankcionovaní stratou polovice bodov.

Veľa riešní bolo úplne správnych, 5 tímov vo svojom skoro správnom riešení zabudlo na vstup "0" a číslo 0 nijako neznázornili. Zopár tímov zabudlo na ešte iné detaily, zopár nevyriešilo záporný vstup a nostatným pár tímom sa nepodarilo riešenie takmer vôbec.

Medzi chyby, ktoré sa opakujú takmer v každej úlohe, ale nepovažujeme ich za menej dôležité patrí používanie globálnych premenných na miestach, kde úplne stačia lokálne premenné. Je pravdepodobné, že väčšina tímov nerozumie správne významu a použitu procedúry, resp. funkcie, a vo väčšine riešení korytnačka skončí na mieste a v otočení takom, ako skončila svoje vykonávanie a chýba jej vrátenie sa na počiatočné miesto a otočenie do počiatočného smeru, čo je možné vidieť aj v galérií k tejto úlohe. Okrem toho používajú v procedúre/funkcii príkazy "domov", "zmaž", "znovu". Vyskytli si aj nesprávne pomenovania procedúry/funkcie alebo súboru.