Autorské riešenie
[stiahni hudobna_skladba1.py, hudobna_skladba2.py]

  • Počet riešiteľov: 8 / 8 =  100.00 %

  • Úspešnosť riešenia: 7.56 / 8 = 94.53 %

Podľa zadania úlohy máme pre zadanú skladbu reprezentovanú zoznamom dvojprvkových zoznamov vrátiť výsledok (intonačnú náročnosť hudobnej skladby) v tvare paťprvkového zoznamu.

Poďme postupne vypočítať jednotlivé prvky paťprvkového zoznamu.

Pri riešení úlohy nás zaujímajú výšky tónov skladby, nie dĺžky tónov skladby, preto je vhodné upraviť pôvodný zoznam dvojprvkových zoznamov na jednoduchý zoznam výšok tónov s vylúčením nečíselnej hodnoty 'r' reprezentujúcej pauzu v skladbe. Dosiahneme to pomocou nasledovných príkazov:

vysky = [prvok[0] for prvok in skladba if prvok[0] != 'r']	  		  

Intonačný rozsah vypočítame ako rozdiel maximálnej a minimálnej hodnoty zoznamu vysky.

intonacny_rozsah = max(vysky) - min(vysky)	  			  

Počet rôznych výšok tónov vypočítame ako veľkosť množiny vytvorenej zo zoznamu vysky.

rozne_vysky = len(set(vysky))	  		  

Premenlivosť skladby vypočítame ako aritmetický priemer absolútnych hodnôt rozdielov výšok susedných tónov,

rozdiely_vysok = [vysky[idx + 1] - vysky[idx] for idx in range(len(vysky) - 1)]
rozdiely_vysok_kladne = [abs(prvok) for prvok in rozdiely_vysok]
premenlivost = sum(rozdiely_vysok_kladne) / len(rozdiely_vysok_kladne)

Najčastejší rozdiel výšok susedných tónov vypočítame preusporadaním hodnôt zoznamu s rozdielmi výšok podľa kritéria počet výskytov a v zostupnom poradí a vybraním nultého prvku takto preusporiadaného zoznamu. Ak sú viaceré takého hodnoty, vyberieme v duchu zadania úlohy jednu z nich.

usporiadane_rozdiely = sorted(rozdiely_vysok, key=rozdiely_vysok.count, reverse=True)
najcastejsi_rozdiel_vysok = usporiadane_rozdiely[0]

Napokon početnosť najčastejšej hodnoty vypočítame pomocou metódy count().

pocetnost = usporiadane_rozdiely.count(najcastejsi_rozdiel_vysok)

Výsledný kompletný program (hudobna_skladba1.py) môže vyzerať napr. nasledovne:

def intonacna_narocnost_skladby(skladba):
    vysky = [prvok[0] for prvok in skladba if prvok[0] != 'r']
    intonacny_rozsah = max(vysky) - min(vysky)
    rozne_vysky = len(set(vysky))
    rozdiely_vysok = [vysky[idx + 1] - vysky[idx] for idx in range(len(vysky) - 1)]
    rozdiely_vysok_kladne = [abs(prvok) for prvok in rozdiely_vysok]
    premenlivost = sum(rozdiely_vysok_kladne) / len(rozdiely_vysok_kladne)
    usporiadane_rozdiely = sorted(rozdiely_vysok, key=rozdiely_vysok.count, reverse=True)
    najcastejsi_rozdiel_vysok = usporiadane_rozdiely[0]
    pocetnost = usporiadane_rozdiely.count(najcastejsi_rozdiel_vysok)
    return [intonacny_rozsah, rozne_vysky, premenlivost, najcastejsi_rozdiel_vysok, pocetnost]

print(intonacna_narocnost_skladby(
[[71, 3], [71, 1], [71, 1], [64, 3], [69, 2], [71, 2], [72, 2], [69, 2], [71, 4], ['r', 4], [69, 3], [69, 1],
[69, 1], [74, 3], [72, 2], [71, 2], [69, 4], [67, 4], ['r', 4], [69, 3], [69, 1], [69, 2], [69, 2], [71, 2],
[71, 2], [67, 2], [64, 2], [66, 2], [66, 2], [66, 2], ['r', 2], [63, 1], [64, 3], [66, 1], [71, 3], [69, 1],
[67, 3], [66, 2], [63, 2], [64, 2], [64, 2], [64, 2], ['r', 2], [67, 3], [69, 1], [71, 1], [71, 3], [72, 3],
[71, 1], [67, 1], [64, 3], [66, 2], [66, 2], [66, 2], ['r', 2], [63, 1], [64, 3], [66, 1], [71, 3], [69, 2],
[67, 2], [66, 2], [63, 2], [64, 2], [64, 2], [64, 2], ['r', 2]]))
			

Ak by sme chceli nájsť nielen jednu ale všetky najpočetnejšie hodnoty rozdielov výšok tónov, použijeme slovník, pomocou ktorého nájdeme najpočetnejšiu hodnotu a napokon pozbierame do zoznamu všetky najpočetnejšie rozdiely výšok susedných tónov. Výsledný program (hudobna_skladba2.py) môže vyzerať napr. nasledovne:

def intonacna_narocnost_skladby(skladba):
    vysky = [prvok[0] for prvok in skladba if prvok[0] != 'r']
    intonacny_rozsah = max(vysky) - min(vysky)
    rozne_vysky = len(set(vysky))
    rozdiely_vysok = [vysky[idx + 1] - vysky[idx] for idx in range(len(vysky) - 1)]
    rozdiely_vysok_kladne = [abs(prvok) for prvok in rozdiely_vysok]
    premenlivost = sum(rozdiely_vysok_kladne) / len(rozdiely_vysok_kladne)
    pocetnosti = {kluc: 0 for kluc in rozdiely_vysok}
    for prvok in rozdiely_vysok:
        pocetnosti[prvok] += 1
    najpocetnejsie = []
    pocetnost = max(pocetnosti.values())
    for kluc in pocetnosti:
        if pocetnosti[kluc] == pocetnost:
            najpocetnejsie.append(kluc)
    return [intonacny_rozsah, rozne_vysky, premenlivost, najpocetnejsie, pocetnost]


print(intonacna_narocnost_skladby(
[[71, 3], [71, 1], [71, 1], [64, 3], [69, 2], [71, 2], [72, 2], [69, 2], [71, 4], ['r', 4], [69, 3], [69, 1],
[69, 1], [74, 3], [72, 2], [71, 2], [69, 4], [67, 4], ['r', 4], [69, 3], [69, 1], [69, 2], [69, 2], [71, 2],
[71, 2], [67, 2], [64, 2], [66, 2], [66, 2], [66, 2], ['r', 2], [63, 1], [64, 3], [66, 1], [71, 3], [69, 1],
[67, 3], [66, 2], [63, 2], [64, 2], [64, 2], [64, 2], ['r', 2], [67, 3], [69, 1], [71, 1], [71, 3], [72, 3],
[71, 1], [67, 1], [64, 3], [66, 2], [66, 2], [66, 2], ['r', 2], [63, 1], [64, 3], [66, 1], [71, 3], [69, 2],
[67, 2], [66, 2], [63, 2], [64, 2], [64, 2], [64, 2], ['r', 2]]))
			

Táto úloha je zameraná na:

  • použitie stratégie riešenia problémov - dekompozíciU problému na podproblémy,

  • precvičenie príkazov volania funkcie s parametrami, príkazov opakovania a vetvenia, použitie metód a funkcií pri práci so zoznamami, prípadne slovníkmi a použitie jednoduchých aritmetických operácií.

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

Do riešenia úlohy sa zapojilo 8 tímov z kategórie GURU. Plný počet bodov získalo až pät tímov file-open, emter, nameless kings, csongorpatka a cestoviny_bez_posypky_s_posypkou, ktorým gratulujeme.

V riešeniach sme zaregistrovali nasledovné nedostatky, vychádzajúce najčastejšie z nedôslednej analýzy problému:

  • nesprávny výpočet najčastejšieho rozdielu výšok a jeho početnosti, (napr. nesprávny výraz v menovateli, nesprávne jeho počiatočné nastavenie na 0),

  • pri výpočtoch odporúčame nepoužívať funkciu round().