De Parsons code (formeel de Parsons Code for Melodic Contours) is een eenvoudige notatie die gebruikt wordt om muziekfragmenten te identificeren door middel van melodische beweging — de beweging van de toonhoogte naar boven en naar beneden. Denys Parsons ontwikkelde het systeem voor zijn boek The Directory of Tunes and Musical Themes uit 1975. Door een melodie op deze manier voor te stellen, is het een stuk eenvoudiger om naar muziekstukken te zoeken, vooral als de noten niet precies gekend zijn.

In de Parsons code wordt de eerste noot van een melodie voorgesteld door een asterisk (*). Elke volgende noot wordt genoteerd als één van drie mogelijke letters die de relatie van de toonhoogte van de noot aangeven in vergelijking met de voorgaande noot:

Deze letters worden de bewegingen van de melodie genoemd. Het verschil in toonhoogte tussen twee opeenvolgende noten wordt in deze voorstelling dus genegeerd. Hieronder zie je bijvoorbeeld een grafische voorstelling van de Parsons code *RUURDDDDRUURDR van het thema Ode to Joy1 (originele Duitse titel: An die Freude) uit de Negende Symfonie van Beethoven, dat gebruikt werd als basis voor het Europese volkslied.

     * R U U R D D D D R U U R D R

+2         *-*                    
          /   \                   
+1       *     *                  
        /       \                 
 0   *-*         *         *-*    
                  \       /   \   
-1                 *     *     *-*
                    \   /         
-2                   *-*          

Als de toonhoogte van de eerste noot gebruikt wordt als referentieniveau (niveau 0), dan beweegt dit thema zich dus tussen twee niveau's onder (-2) en twee niveau's boven (+2) het referentieniveau. We noemen dit respectievelijk de maximale afwijking naar onder en de maximale afwijking naar boven.

Deze voorstelling blijkt verrassend effectief te zijn. Parsons, die vijf jaar van zijn leven spendeerde aan het indexeren van bijna alle bekende klassieke melodieën vanaf de 16e eeuw, schreef hierover

I continue to be astonished that such a simple test, taken to the sixteenth note (or less), should be adequate to distinguish more than 10.000 classical themes.

Kan je bijvoorbeeld de klassieke melodieën identificeren waarvan de Parsons code hieronder wordt weergeven? Klik hier om het antwoord zichtbaar te maken.

  1. *RUDUDDRUDUD

  2. *RURURDDRDRDRDURDRDRDURDRDRDDRURURDDRDRDRD

  3. *UDDUUDDURDURDURUDDDUDDURUDDDUDDURUDDUUDDDUDDD

  4. *UDUUDUDDDUU

  5. *UDDUUUU

  6. *RRURDDRDRRURDUDURRRRDDRDUUDDRDU

  7. *RDUDUURURDRDDRUDUDUU

  8. *RRDURRD

  9. *RUURURDRDRUURURDR

  10. *DUDUDUUUDDUDUDDUD

  11. *DUDDDDDUDDUDUDU

  12. *UDUUDUDUUDUDUUDUDUU

  13. *DUDUDUDURRRRRRRRDUDU

  14. *RRRRRRRUUUDRRRRUURDDD

Opgave

We stellen een Parsons code voor als een string (str) die start met een asterisk (*) en die verder enkel de letters U, D en R bevat. Bij een Parsons code wordt geen onderscheid gemaakt tussen hoofdletters en kleine letters.

Een contourplot is een grafische voorstelling van een Parsons code in de vorm van een rechthoekig rooster. Hieronder zie je bijvoorbeeld de contourplot van de Parsons code *RUURDDDDRUURDR, waarbij de lege cellen spaties voorstellen.

contourplot
Contourplot van de Parsons code *RUURDDDDRUURDR.

De toonhoogte van de eerste noot wordt in de eerste kolom aangegeven met een asterisk (*). Elke beweging van de Parsons code zet twee bewegingstekens in de volgende twee kolommen van het rooster: bij de letter U worden de tekens / en * telkens een rij hoger gezet, bij de letter D worden de tekens \ en * telkens een rij lager gezet, en bij de letter R worden de tekens - en * telkens op de huidige rij gezet. Het rooster van de contourplot wordt zo gekozen dat de eerste en de laatste kolom respectievelijk corresponderen met de eerste en de laatste noot, en dat de eerste en de laatste rij respectievelijk corresponderen met de maximale afwijking naar boven en naar onder. Gevraagd wordt:

Backslashes in strings

Strings in Python gebruiken het backslash karakter (\) voor het escapen van karakters die anders een speciale betekenis zouden krijgen, zoals een newline ('\n'), een enkel aanhalingsteken ('\'') of een dubbel aanhalingsteken ("\""). Om letterlijke backslashes op te nemen in strings (ook docstrings) moeten die backslashes dus verdubbeld worden:

>>> print('Antwoord met ja\neen')
Antwoord met ja
een
>>> print('Antwoord met ja\\neen')
Antwoord met ja\neen

Voorbeeld

In onderstaande voorbeeldsessie gaan we ervan uit dat de tekstbestanden parsons_01.txt16, parsons_02.txt17 en parsons_03.txt18 zich in de huidige directory bevinden.

>>> maximale_afwijking('*RUURDDDDRUURDR')
(-2, 2)
>>> maximale_afwijking('*uduududdduu')
(-1, 2)
>>> maximale_afwijking('*DRRUUDDRUURDUDURDDU')
(-1, 1)

>>> parsons('parsons_01.txt19')
'*RUURDDDDRUURDR'
>>> parsons('parsons_02.txt20')
'*UDUUDUDDDUU'
>>> parsons('parsons_03.txt21')
'*DRRUUDDRUURDUDURDDU'

>>> contour('*RUURDDDDRUURDR')
      *-*                    
     /   \                   
    *     *                  
   /       \                 
*-*         *         *-*    
             \       /   \   
              *     *     *-*
               \   /         
                *-*          
>>> contour('*RUURDDDDRUURDR', 'contour_01.txt22')
>>> contour('*uduududdduu')
        *   *          
       / \ / \         
  *   *   *   *       *
 / \ /         \     / 
*   *           *   *  
                 \ /   
                  *    
>>> contour('*uduududdduu', 'contour_02.txt23')
>>> contour('*DRRUUDDRUURDUDURDDU')
          *         *-*   *   *-*      
         / \       /   \ / \ /   \     
*       *   *     *     *   *     *   *
 \     /     \   /                 \ / 
  *-*-*       *-*                   *  
>>> contour('*DRRUUDDRUURDUDURDDU', 'contour_03.txt24')

Bronnen