Traccia: Ajeje la bibliotecaria ha recentemente trovato una stanza nascosta nella biblioteca di Keras (un posto fantastico situato in Umkansa, il villaggio più grande delle Montagne Bianche). Lì ha scoperto diversi libri contenenti spartiti musicali di antiche canzoni Tarahumara e ha, quindi, invitato un amico musicista a dare un’occhiata. Il musicista le ha detto che è una scoperta sensazionale, dato che gli spartiti sono scritti in notazione Tarahumara, una popolazione ormai estinta, ma molto famosa per aver influenzato i musicisti della Sierra Nevada. Per poter riprodurre i brani le suggerisce di farli tradurre in una notazione familiare ai musicisti Umkansaniani, ultimi discendenti dei Tarahumara, in modo che possano riprodurli.

I Tarahumara scrivevano le note usando numeri invece di lettere: 0 al posto di A, 1 al posto di B e così via, fino a 7 al posto di G. Le note bemolle (b) e diesis (#) (vedi la nota 3 sotto, se non sai cosa sono bemolle e diesis) erano seguite rispettivamente da un - e da un + (ad esempio, 0- significa A bemolle). Inoltre, ripetevano semplicemente lo stesso numero più volte per rappresentare la durata della nota. Ad esempio, 0000 significa che la nota A ha una lunghezza di 4, mentre 0-0-0-0- significa che la nota A bemolle ha una lunghezza di 4.

Le pause venivano scritte come spazi: ad esempio, dodici spazi rappresentano una pausa lunga 12. Sia le note che le pause potevano estendersi su diverse linee della partitura (ad esempio, iniziando dalla linea x e continuando sulla riga x+1, x+2 e così via). Infine, gli spartiti musicali erano scritti da destra a sinistra e dall’alto verso il basso, mentre andare accapo non significava nulla in termini di partitura musicale.

Gli Umkansaniani, invece, sono soliti scrivere le note utilizzando lettere, e ogni nota è seguita dalla sua durata (quindi, l’esempio sopra verrebbe scritto come A4). Le note bemolle e diesis sono seguite rispettivamente da una ‘b’ o da una ’#’ (ad esempio, A bemolle è scritto Ab, quindi l’esempio sopra verrebbe scritto ad Ab4). Le pause vengono scritte utilizzando la lettera P, seguita dalla loro durata e non viene utilizzato alcuno spazio. Infine, gli Umkansaniani sono abituati a leggere la musica da sinistra a destra, scritta su una singola riga.

Poiché Ajeje sa che sei un abile programmatore, ti fornisce una cartella contenente la trascrizione di tutte le canzoni di Tarahumara che ha trovato, organizzate in più sottocartelle e file (un brano per file). Inoltre, ha preparato un file indice in cui ogni riga contiene il titolo di una canzone Tarahumara (tra virgolette), seguito da uno spazio e dal percorso del file contenente quella canzone (tra virgolette, relativa alla cartella principale). Vorrebbe tradurre tutte le canzoni elencate nell’indice e salvarle in nuovi file, ciascuno denominato con il titolo della canzone che contiene (con estensione .txt), in una struttura di cartelle corrispondente a quella originale. Inoltre, vorrebbe archiviare nella cartella principale della struttura creata un file indice contenente su ogni riga il titolo di una canzone (tra virgolette) e la corrispondente lunghezza del brano, separati da uno spazio. Le canzoni nell’indice devono essere ordinate per lunghezza decrescente e, se la durata di alcuni brani è la stessa, in ordine alfabetico ascendente. La durata di una canzone è la somma delle durate di tutte le note e delle pause di cui è composta.

Sarai capace di aiutare Ajeje nel tradurre le canzoni Tarahumara in canzoni Umkansaniane?

Nota 0: di seguito viene fornita una funzione per Umkansanizzare le canzoni di Tarahumara; dopo essere stata eseguita, deve restituire un dizionario in cui ogni chiave è il titolo di una canzone ed il valore associato è la durata del brano.

Nota 1: l’indice delle canzoni da tradurre è il file ‘index.txt’ che si trova nella directory passata nell’argomento source_root

Nota 2: l’indice delle canzoni tradotte è il file ‘index.txt’ che deve essere creato nella directory passata nell’argomento target_root

Nota 3: le note bemolle e diesis sono solo versioni “alterate”. di note regolari; per esempio un A# (“A diesis”) è la versione alterata di un A, cioè una nota A che è un mezzo tono più alto del A regolare; lo stesso vale per note bemolle, che sono mezzo tono più basse delle note normali; dal punto di vista dei compiti, note bemolle e diesis devono essere trattate allo stesso modo delle note regolari (ad eccezione della loro notazione).

Nota 4: Usiamo la notazione inglese delle note A B C D E F G.

Nota 5: potete usare le funzioni della libreria ‘os’ per creare le directory necessarie (ad esempio os.makedirs)

Mia Soluzione:

import os
 
def translate(song):
     
    file = open(song, 'r')
    text = file.read()
    file.close()
    text = ''.join([line[::-1] for line in text.split('\n')])
    text = text.translate(str.maketrans('0123456+- ','ABCDEFG#bP')) 
    text = text[::-1]+ '\n\n'
    
    return_text = []
    
    if text[0] in '#b':
        current_char = text[0:2]
        i = 2
        length = 2
    else:
        current_char = text[0]
        i = 1
        length = 1
 
    char_count = 1
    song_length = 0
 
    while text[i] != '\n':
        
        if text[i:i+length] == current_char:
            char_count += 1
            i += length
        else:
            return_text.append(str(char_count)[::-1] + current_char)
            if text[i] in '#b':
                current_char = text[i:i+2]
                length = 2
                i += 2
            else:
                current_char = text[i]
                length = 1
                i += 1
            song_length += char_count
            char_count = 1
 
        
    song_length += char_count
    return_text.append(str(char_count)[::-1] + current_char)
    
    return (''.join(return_text)[::-1], song_length)
 
def Umkansanize(source_root:str, target_root:str) -> dict[str,int]:
    
    file = open(source_root + '/index.txt', 'r')
    src_index_txt = file.read()
    file.close()
    
    src_index = src_index_txt.split('\n')[:-1]
    new_index = {}
    for elem in src_index:
        elem = elem.split('"')
        name = elem[1]
        root = elem[3]
        translated, length = translate(f'{source_root}/{root}')
        new_index[name] = length
 
        root = root.split('/')
        root = '/'.join(root[:-1])
        new_root = f'{target_root}/{root}'
        os.makedirs(new_root,exist_ok=True)
        
        file = open(f'{new_root}/{name}.txt', 'w')
        file.write(translated)
        file.close()
        
    to_write = []
    for k, v in sorted(new_index.items(), key=lambda x:(-x[1],x[0])):
        to_write.append(f'"{k}" {new_index[k]}\n')
        
    file = open(f'{target_root}/index.txt', 'w')
    file.write(''.join(to_write))
    file.close()
        
    return new_index