Je hebt een laboratoriumexperiment opgezet waarbij je bismutatomen aan de hand van een deeltjesversneller bombardeert met zink. Met dit experiment ben je erin geslaagd om een groot aantal nieuwe chemische elementen te maken. Aangezien deze elementen tot op vandaag nog onbekend bleven, zal de ontdekking je ongetwijfeld de Nobelprijs voor de Scheikunde opleveren. Om je resultaten te kunnen publiceren, moet je echter voor alle elementen nog een nieuwe naam zien te verzinnen.
Omdat je namen wilt geven die analoog zijn aan de namen voor bestaande chemische elementen, besluit je om op de volgende manier te werk te gaan. Chemische namen worden geschreven met een hoofdletter, gevolgd door twee of meer kleine letters. Dus hou je ook vast aan dit gebruik van hoofdletters en kleine letters. Om de uitgangen van elementnamen te herkennen, voeg je achteraan de namen van alle bestaande chemische elementen (tijdelijk) een underscore (_) toe. Voor de rest ga je als volgt te werk:
Kies willekeurig een naam van een bestaand chemisch element, en neem de eerste drie letters daarvan als beginletters voor de nieuwe naam die je gaat construeren.
Neem de laatste twee letters van de voorlopige nieuwe naam, en zoek binnen de namen van de bestaande chemische elementen naar alle mogelijke karakters (kleine letters of een underscore) die volgen op dit letterpaar. Kies een willekeurige karakter uit deze lijst van mogelijkheden, en voeg het achteraan toe aan de nieuwe naam.
Als je in stap 2 een underscore hebt gekozen, dan beschouw je de nieuwe naam als afgewerkt. Je verwijdert uiteraard de underscore op het einde van de naam. Zolang je echter in stap 2 een letter kiest, blijf je stap 2 herhalen.
Als bovenstaande procedure een naam oplevert die reeds bestaat, dan herhaal je de procedure totdat ze een nieuwe naam oplevert.
Definieer een klasse NaamGenerator die kan gebruikt worden om volgens de hierboven beschreven procedure nieuwe namen te genereren op basis van een reeks voorbeeldnamen. De objecten van deze klasse moeten minstens over de volgende eigenschappen en methoden beschikken:
Elk object van de klasse NaamGenerator moet gegarandeerd de eigenschappen prefixen en triples hebben. Bij het aanmaken van een nieuw object moeten deze eigenschappen respectievelijk verwijzen naar een lege verzameling en een lege dictionary. De volgende twee methoden worden gebruikt om de inhoud van deze eigenschappen te wijzigen.
Een methode naam_toevoegen waarmee een nieuwe voorbeeldnaam aan de generator kan toegevoegd worden. Deze voorbeeldnaam moet als stringargument aan de methode doorgegeven worden. De methode moet ervoor zorgen dat een string met de eerste drie letters van de voorbeeldnaam aan de verzameling van prefixen (eigenschap prefixen) toegevoegd wordt, en dat ook de dictionary van triples (eigenschap triples) wordt bijgewerkt. Dit laatste gebeurt door elk paar opeenvolgende kleine letters van de voorbeeldnaam op te zoeken als sleutel in de dictionary, en de daaropvolgende letter van de voorbeeldnaam (of een underscore voor het laatste letterpaar) toe te voegen aan de verzameling die door de dictionary op die sleutel wordt afgebeeld. Indien het letterpaar nog niet als sleutel voorkwam in de dictionary, dan moet een nieuw sleutel/waarde paar aangemaakt worden, met als waarde een verzameling die de letter bevat die volgt op het letterpaar. De methode moet een AssertionError met de tekst ongeldige naam opwerpen indien de voorbeeldnaam die als argument wordt doorgegeven niet bestaat uit een hoofdletter, gevolgd door twee of meer kleine letters.
Een methode namen_toevoegen waaraan de locatie van een tekstbestand als argument moet doorgegeven worden. Dit tekstbestand moet een lijst van namen bevatten, elk op een afzonderlijke regel. De methode moet ervoor zorgen dat elk van deze namen gebruikt wordt om de eigenschappen prefixen en triples bij te werken, conform de beschrijving die we hebben gegeven bij de methode naam_toevoegen.
Een methode naam waaraan geen argumenten moeten doorgegeven worden. Deze methode moet een nieuwe naam teruggeven die werd gegenereerd op basis van de procedure die in de inleiding werd besproken. Uiteraard wordt hierbij in stap 1 gebruikgemaakt van de eigenschap prefixen, en in stap 2 van de eigenschap triples. De voorbeeldnamen die werden doorgegeven bij het aanroepen van de methode naam_toevoegen of die in een tekstbestand voorkwamen dat werd opgegeven bij het aanroepen van de methode namen_toevoegen, worden niet als nieuwe namen beschouwd en mogen dus ook niet door de methode teruggeven worden.
Zorg er bij de implementatie van al deze methoden voor dat je optimaal gebruik maakt van de methoden die je reeds eerder geïmplementeerd hebt.
Bij onderstaande voorbeeldsessie gaan we ervan uit dat het bestand shortlist_elementen.txt1 zich in de huidige directory bevindt.
>>> chemGen = NaamGenerator()
>>> chemGen.naam
_toevoegen('Osmium')
>>> chemGen.prefixen
{'Osm'}
>>> chemGen.triples
{'um': {'_'}, 'iu': {'m'}, 'mi': {'u'}, 'sm': {'i'}}
>>> chemGen.naam
_toevoegen('bismut')
Traceback (most recent call last):
AssertionError: ongeldige naam
>>> chemGen.naam
_toevoegen('zINC')
Traceback (most recent call last):
AssertionError: ongeldige naam
>>> chemGen.naam
_toevoegen('pH')
Traceback (most recent call last):
AssertionError: ongeldige naam
>>> chemGen.naam
_toevoegen('Bismut')
>>> chemGen.prefixen
{'Osm', 'Bis'}
>>> chemGen.triples
{'mu': {'t'}, 'mi': {'u'}, 'is': {'m'}, 'iu': {'m'}, 'um': {'_'}, 'sm': {'i', 'u'}, 'ut': {'_'}}
>>> chemGen.namen
_toevoegen('shortlist_elementen.txt')
>>> chemGen.prefixen
{'Lan', 'Tel', 'Unu', 'Plu', 'Osm', 'Rut', 'Bis', 'Tha'}
>>> chemGen.triples
{'el': {'l'}, 'en': {'i'}, 'is': {'m'}, 'iu': {'m'}, 'al': {'l'}, 'an': {'i', 't'}, 'xi': {'u'}, 'ex': {'i'}, 'er': {'f'}, 'nh': {'e'}, 'ni': {'u'}, 'll': {'i', 'u'}, 'di': {'u'}, 'li': {'u'}, 'rd': {'i'}, 'to': {'n'}, 'rf': {'o'}, 'lu': {'u', 't'}, 'th': {'a', 'e'}, 'fo': {'r'}, 'nt': {'h'}, 'nu': {'n'}, 'on': {'i'}, 'ha': {'l', 'n'}, 'he': {'x', 'r', 'n'}, 'um': {'_'}, 'uu': {'r'}, 'ut': {'h', 'o', '_'}, 'mi': {'u'}, 'ur': {'_'}, 'mu': {'t'}, 'un': {'h'}, 'sm': {'i', 'u'}, 'or': {'d'}}
>>> chemGen.naam()
'Osmuthalluthexium'
>>> chemGen.naam()
'Ruthanthanium'
>>> chemGen.naam()
'Lantherfordium'
>>> chemGen.naam()
'Thanthenium'