Om te weten waar een woord op het einde van een regel mag afgebroken worden, gebruiken tekstverwerkers een algoritme om te bepalen hoe woorden op een correcte manier in lettergrepen moeten gesplitst worden. Dit algoritme is gebaseerd op een lijst van patronen die aangeven waar wel en waar niet mag gesplitst worden. Het patroon 1tion geeft bijvoorbeeld aan dat het woord station moet gesplitst worden als sta-tion, en het patroon t1t geeft aan dat het woord letter moet gesplitst worden als let-ter. In beide gevallen geeft het oneven getal 1 aan waar er op een correcte manier mag gesplitst worden.

Er zijn ook uitzonderingen op de splitsingsregels nodig. Het patroon 1tion zou het woord cation immers verkeerdelijk splitsen als ca-tion in plaats van als cat-ion. Daarom bestaan er ook patronen die aangeven op welke plaatsen er niet mag gesplitst worden. Zo maakt het patroon .ca2t bijvoorbeeld het voorgaande patroon ongedaan, waardoor de splitsing ca-tion onmogelijk wordt. Hierbij geeft het even getal 2 in het patroon aan dat er op deze plaats niet mag gesplitst worden. Een patroon dat begint met een punt geeft aan dat het patroon enkel van toepassing is aan het begin van een woord. Analoog geeft een patroon dat eindigt met een punt aan dat het patroon enkel van toepassing is op het einde van een woord. Uiteraard zijn er ook uitzonderingen op de uitzonderingen mogelijk. Bovendien heeft elke taal zijn eigen splitsingsregels, die vervat zitten in een taalspecifieke lijst van patronen.

Het algoritme dat we in deze opgave zullen gebruiken voor het splitsen van woorden in lettergrepen, werkt tot vijf niveaus diep — splitsen (1), niet-splitsen (2), splitsen (3), niet-splitsen (4), splitsen (5). Hierbij worden de eerste en de laatste letter van een woord nooit afzonderlijk afgesplitst.

We leggen de werking van het algoritme uit aan de hand van onderstaand voorbeeld, dat aangeeft hoe het woord lettergrepen op een correcte manier in lettergrepen moet gesplitst worden (in het Nederlands). Op dit woord zijn de patronen r1g, 1te, e1pe, t2er, 4t3t, t5te, .l4, 1gr4 en 4n. van toepassing. Onderstaand schema geeft aan hoe deze patronen gebruikt worden om het woord lettergrepen te splitsen in lettergrepen.

. l e t t e r g r e p e n .
            r1g
       1t e
     4t3t
                  e1p e
        t2e r
      t5t e
. l4
             1g r4
                       4n .
.0l4e4t5t2e0r1g0r4e1p0e4n0.
  l e t-t e r-g r e-p e n

Nadat alle patronen werden gevonden die op het woord van toepassing zijn, bepaalt het hoogste cijfer op elke positie tussen twee karakters (letters of punten) of op die positie mag gesplitst worden of niet. Dit hoogste cijfer noemen we een regel. Een regel tussen twee karakters is gelijk aan nul (0) als er met die positie geen enkel cijfer van een patroon correspondeert.

Even regels (inclusief nullen) geven aan waar er niet mag gesplitst worden. Oneven regels geven aan waar er wel mag gesplitst worden. Er mogen met andere woorden enkel koppeltekens ingevoegd worden op posities die corresponderen met oneven regels. Bovendien mogen er nooit koppeltekens geplaatst worden voor en na de eerste en de laatste letter van het woord. Deze posities worden in bovenstaand schema in het rood aangeduid.

Opgave

Een woord bestaat uit één of meer letters. Woorden bevatten dus nooit karakters die geen letter zijn. De letters van een woord mogen wel diaktritische tekens1 hebben, zoals in archaïsch, einzelgänger, saté, scène, enquête, façade, mañana, smørrebrød en ångström.

Een patroon bestaat uit één of meer letters, die ook diakritische tekens mogen hebben. Aan het begin en/of het einde van een patroon kan een punt (.) staan. Tussen elke twee karakters (letters of punten) van een patroon kan een cijfer (09) staan.

De splitsingsregels van een taal worden beschreven door een collectie patronen in een tekstbestand (één patroon per regel). Omdat patronen letters met diakritische tekens kunnen hebben, gebruiken dergelijke bestanden een UTF-8 tekencodering2.

Definieer een klasse Lettergrepen om woorden in lettergrepen te splitsen volgens de regels van een bepaalde taal. Bij het aanmaken van een nieuwe splitser (Lettergrepen) moet de locatie (str) doorgegeven worden van het tekstbestand met splitsingsregels voor de taal. Hou rekening met het feit dat het aantal patronen voor een taal kan oplopen tot meer dan $$10^4$$.

Op een splitser $$s$$ (Lettergrepen) moet je minstens de volgende methoden kunnen aanroepen:

De methoden regels en splitsen moeten het gebruik van hoofdletters en kleine letters in woord $$w$$ behouden.

Voorbeeld

Bij onderstaande voorbeeldsessie gaan we ervan uit dat het tekstbestand patronen.nl.txt3 zich in de huidige directory bevindt.

>>> nederlands = Lettergrepen('patronen.nl.txt4')

>>> nederlands.patronen('lettergrepen')
{'r1g', '1gr4', 'e1pe', 't5te', '1te', '4n.', 't2er', '4t3t', '.l4'}
>>> nederlands.patronen('Babbelaar')
{'.b4', '3b4e', 'a4a4', '3ba', '4bb', '4ar.', '1b', '4r.', 'e1la'}
>>> nederlands.patronen('slaapmutsje')
{'1mu', '2s3je.', '4ts', '4e.', '5slaap', '2p1m', 'a4a4', '5mut', 'sj2', '.s4', 's2l4', 'muts2', 'ts2j', 's1je'}
>>> nederlands.patronen('TROUBADOUR')
{'5dou', 'tr4', '3ba', '1do', '2u2b', '3trou', '1b', '4r.', '.t4'}

>>> nederlands.regels('lettergrepen')
'.0l4e4t5t2e0r1g0r4e1p0e4n0.'
>>> nederlands.regels('Babbelaar')
'.3B4a4b3b4e1l0a4a4r0.'
>>> nederlands.regels('slaapmutsje')
'.5s4l4a4a4p5m0u4t2s3j4e0.'
>>> nederlands.regels('TROUBADOUR')
'.3T4R4O2U3B0A5D0O0U4R0.'

>>> nederlands.splitsen('lettergrepen')
'let-ter-gre-pen'
>>> nederlands.splitsen('Babbelaar')
'Bab-be-laar'
>>> nederlands.splitsen('slaapmutsje')
'slaap-muts-je'
>>> nederlands.splitsen('TROUBADOUR')
'TROU-BA-DOUR'

Epiloog

Kabouter Wesley5: De vriendschapsfee (aflevering 28)

Bronnen