Autorské riešenie
[stiahni py]

  • Počet riešiteľov: 10 / 23 = 43 %

  • Úspešnosť riešenia: 5,4 / 8 = 68 %

Túto úlohu môžeme riešiť dvoma spôsobmi.

V prvom prípade budeme prechádzať zadaným textom, analyzovať znak po znaku, aby sme zistili, či sme našli oddeľovať slov (a zvýšili počet nájdených slov) alebo oddeľovač viet (a vypočítali náročnosť vety).

 Druhá možnosť je upraviť text tak, aby ho bolo možné jednoducho rozdeliť na vety a vo vetách spočítať slová. Tento spôsob je výhodnejší v tom, že vo väčšej miere budeme používať funkcie jazyka a menej sa spoliehať na našu analýzu. Je tak menej pravdepodobné, že v riešení urobíme chybu. Pozrime sa bližšie na tento spôsob.

Aby sme mohli vypočítať náročnosť testu, potrebujeme vedieť:

  • koľko je v texte viet,

  • koľko slov má každá veta slov.

Situáciu nám komplikuje fakt, že: "Pred a za slovami či vetami je viacero medzier alebo voľných riadkov. Bodky, výkričníky, otázniky, čiarky, dvojbodky či úvodzovky sú na tom ešte horšie. Pri nich navyše občas medzery chýbajú. "

Podľa tohto opisu by mohol text vyzerať napr. takto:

ukazka textu 1

Takto neporiadne napísaný text by podľa typografických pravidiel mal vyzerať nasledovne:

ukazka textu 2

Text potrebujeme rozdeliť na vety a v každej vete identifikovať počet slov. Slová vo vetách sú oddelené medzerou a vety sú oddelené jedným zo znakov: .!?:

Potrebovali by sme text upraviť tak, aby sme ho vedeli rozdeliť na vety a v každej vete spočítať slová. Oddeľovačom viet môže byť bodka a oddeľovačom slov medzera. Napríklad takto:

ukazka textu 3

Takto upravený text ľahko rozdelíme na vety a v každej vete ľahko spočítame slová.

Funkcia na úpravu textu môže vyzerať nasledovne:

# Python
def uprav_text(text):
    # všetky oddeľovače slov nahradíme medzerou
    text = text.replace('\n', ' ')
    text = text.replace('„', ' ')
    text = text.replace('“', ' ')
    text = text.replace(',', ' ')
    
    # všetky oddeľovače viet nahradíme bodkou
    text = text.replace('!', '.')
    text = text.replace('?', '.')
    text = text.replace(':', '.')

    # viaceré medzery za sebou nahradíme jednou
    while text.find('  ') != -1:
        text = text.replace('  ', ' ')

    # ak pri nejakej bodke ostala medzera, vymažeme ju
    text = text.replace('. ', '.')
    text = text.replace(' .', '.')

    # ak na konci textu ostala bodka, vymažeme ju
    if text[-1] == '.':
        text = text[:-1]

    # ak na koncoch textu ostala nejaká medzera, vymažeme ju
    text = text.strip()
    return text

Ak už máme text upravený, môžeme vypočítať jeho náročnosť.

# Python
def narocnost_vety(veta):
    pocet_slov = veta.count(' ') + 1
    narocnost = pocet_slov ** 1.1
    return narocnost


def narocnost_textu(text):
    text = uprav_text(text)
    narocnost = 0
    vety = text.split('.')
    for veta in vety:
        narocnost = narocnost + narocnost_vety(veta)
    return narocnost

V riešení do veľkej miery využívame textové funkcie. Pri úprave sme nahrádzali časti textu (''.replace()), vyhľadávali v texte (''.find()), vyberali časti reťazcov (''.[:-1]) alebo odstraňovali netlačiteľné znaky z jeho koncov (''.strip()).

Upravený text sme rozdelili na vety (''.split()) a v každej vete sme spočítali medzery (''.count()), aby sme zistili počet slov.

Manipulácia s textami je pre počítač vo všeobecnosti náročná. Ide hlavne o prípady, keď spracovávame rozsiahle texty. Programovacie jazyky preto často poskytujú aj iné, efektívnejšie spôsoby ako s textami pracovať. Jedným z nich sú regulárne výrazy. Ak by sme v riešení využili regulárne výrazy, celé riešenie môže vyzerať nasledovne: 

# Python
import re


def narocnost_vety(veta):
    pocet_slov = veta.count(' ') + 1
    narocnost = pocet_slov ** 1.1
    return narocnost


def uprav_text_na_vety(text):
    # všetky postupnosti oddeľovačov slov nahradíme medzerou
    text = re.sub('[ \n„“,]+', ' ', text)

    # zbavíme sa medzier na začiatku a oddeľovača vety
    # (s pripadnými medzerami) na konci textu
    text = re.sub('^ *(\S.*\S) *[!?:\.] *$', '\\1', text)

    # rozdelíme text na vety podľa oddeľovačov viet, 
    # ktoré môžu mať okolo seba medzery
    vety = re.split(' *[!?:\.] *', text)
    return vety


def narocnost_textu_re(text):
    vety = uprav_text_na_vety(text)
    narocnost = 0
    for veta in vety:
        narocnost = narocnost + narocnost_vety(veta)
    return narocnost

Túto verziu riešenia úlohy sme uviedli len preto, aby sme ukázali, že každé riešenie je možné ešte vylepšiť. Ak vás použitie regulárnych výrazov zaujalo, viac sa o ňom dozviete napr. na:

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

Pri riešení úlohy ste sa snažili rozložiť zadaný text na vety - využili ste to, že veta končí niektorým zo znakov ., :, ?, !. Takto získané vety ste prechádzali a ako oddeľovače slov ste využili čiarky a medzery. Zabudli ste však vhodne spracovávať úvodzovky, ktorými končila veta priamej reči - výsledkom bol vyšší počet viet. Niektorí z vás nevyriešili situáciu s viacriadkovým textom - program fungoval správne len vtedy, ak išlo o jeden riadok. Tím HairyElephants ako jediný z tímov využil pri riešení úlohy regulárne výrazy.

V autorskom riešení sme uvažovali slovenské úvodzovky „“, ale vo vašich riešeniach sme akceptovali ľubovoľné.