In zijn Novembernummer van 2011 publiceerde NWT Magazine onderstaande Metrokaart der exacte wetenschap. De uitdaging van deze opgave bestaat erin om nieuwe gegevenstypes aan Python toe te voegen die toelaten om dergelijke metrokaarten op te stellen, uit te breiden en te bevragen. Een metrokaart is opgebouwd uit een aantal metrolijnen die verschillende metrostations in een vaste volgorde met elkaar verbinden. Het verkeer op een metrolijn verloopt dus in één richting, en bij deze opgave vormen metrolijnen ook nooit een lus. Sommige metrostations kunnen wel op verschillende metrolijnen liggen, zodat daar van de ene op de andere lijn kan overgestapt worden.

metrokaart der exacte wetenschappen
Metrokaart der exacte wetenschappen

Opgave

Definieer een klasse Station waarmee de metrostations op een metrokaart kunnen voorgesteld worden. Elk metrostation beschikt over de eigenschappen naam, jaar en omschrijving, die telkens verwijzen naar een string (het jaartal kan ook beschreven worden door bv. 6e eeuw v. Chr.). Vanuit elk metrostation kan je vertrekken naar nul of meer andere metrostations, maar elk van deze uitgaande verbindingen liggen op een verschillende metrolijn. Om deze uitgaande verbindingen voor te stellen, beschikt elk metrostation ook over een eigenschap lijnen die verwijst naar een dictionary. Deze dictionary geeft de metrolijnen aan die vertrekken vanuit het station, door telkens de naam van een metrolijn (een string; hier steeds de naam van een exacte wetenschap) af te beelden op het volgende metrostation op die lijn.

metrostation
Schematische voorstelling van de objecten van de klasse Station.

De objecten van de klasse Station moeten verder minstens over de volgende methoden beschikken:

Definieer een klasse Metrokaart waarmee metrokaarten kunnen voorgesteld worden. Metrokaarten zijn opgebouwd uit een aantal metrolijnen die verschillende metrostations in een vaste volgorde met elkaar verbinden. Elke metrokaart beschikt over een eigenschap lijnen, die verwijst naar een dictionary. Deze dictionary beeldt voor elke metrolijn op de metrokaart de naam van de lijn (een string; hier steeds de naam van een exacte wetenschap) af op het beginstation van de metrolijn (een object van de klasse Station). De objecten van de klasse Metrokaart moeten verder minstens over de volgende methoden beschikken:

Zorg er bij de implementatie van de klassen Station en Metrokaart voor dat je telkens optimaal gebruik maakt van de methoden die je reeds eerder geïmplementeerd hebt.

Voorbeeld (klasse Station)

>>> station1 = Station('James Watson', '1953', 'opheldering DNA-structuur')
>>> station1.naam
'James Watson'
>>> station1.jaar
'1953'
>>> station1.omschrijving
'opheldering DNA-structuur'
>>> station1.lijnen
{}
>>> station1 == station1
True
>>> station1
Station(naam='James Watson', jaar='1953', omschrijving='opheldering DNA-structuur')

>>> station2 = Station(naam='Ernst Mayr', jaar='1942', omschrijving='biologische soorten')
>>> print(station2)
Ernst Mayr (1942, biologische soorten)
>>> station1 == station2
False

>>> station1.verbind('biologie', station2)
>>> station1.lijnen
{'biologie': Station(naam='Ernst Mayr', jaar='1942', omschrijving='biologische soorten')}
>>> station1.volgende('biologie')
Station(naam='Ernst Mayr', jaar='1942', omschrijving='biologische soorten')
>>> print(station1.volgende('chemie'))
None

>>> station3 = Station('Marshall Warren Nirenberg', '1962', 'genetische code')
>>> station4 = Station('Ilya Prigogine', '1955', 'zelf-organisatie en niet-evenwicht')    
>>> station1.verbind('chemie', station3)
>>> station1.verbind('chemie', station4)
Traceback (most recent call last):
AssertionError: station is reeds verbonden op lijn chemie
>>> station1.verbind('genomica', station4)
>>> station1.lijnen
{'biologie': Station(naam='Ernst Mayr', jaar='1942', omschrijving='biologische soorten'), 'genomica': Station(naam='Ilya Prigogine', jaar='1955', omschrijving='zelf-organisatie en niet-evenwicht'), 'chemie': Station(naam='Marshall Warren Nirenberg', jaar='1962', omschrijving='genetische code')}
>>> print(station1.volgende('chemie'))
Marshall Warren Nirenberg (1962, genetische code)
>>> print(station1.volgende('genomica'))
Ilya Prigogine (1955, zelf-organisatie en niet-evenwicht)

Voorbeeld (klasse Metrokaart)

Bij onderstaande voorbeeldsessie gaan we ervan uit dat het tekstbestand mijlpalen.txt1 zich in de huidige directory bevindt.

>>> kaart = Metrokaart()
>>> kaart.uitbreiden('genomica', Station('James Watson', '1953', 'opheldering DNA-structuur'))
>>> kaart.uitbreiden('genomica', Station('Marshall Warren Nirenberg', '1962', 'genetische code'))
>>> kaart.uitbreiden('genomica', Station(naam='Frederick Sanger', jaar='1977', omschrijving='sequencing'))
>>> kaart.beginstation('genomica')
Station(naam='James Watson', jaar='1953', omschrijving='opheldering DNA-structuur')
>>> kaart.eindstation('genomica')
Station(naam='Frederick Sanger', jaar='1977', omschrijving='sequencing')
>>> kaart.uitbreiden('chemie', Station('Robert Boyle', '1661', 'The Sceptical Chymist'))
>>> kaart.beginstation('chemie')
Station(naam='Robert Boyle', jaar='1661', omschrijving='The Sceptical Chymist')
>>> kaart.eindstation('chemie')
Station(naam='Robert Boyle', jaar='1661', omschrijving='The Sceptical Chymist')

>>> kaart2 = Metrokaart('mijlpalen.txt')
>>> kaart2.beginstation('chemie')
Station(naam='Robert Boyle', jaar='1661', omschrijving='The Sceptical Chymist')
>>> kaart2.eindstation('chemie')
Station(naam='Paul Crutzen', jaar='1985', omschrijving='atmosfeerchemie')

>>> station = kaart2.beginstation('genomica')
>>> station
Station(naam='James Watson', jaar='1953', omschrijving='opheldering DNA-structuur')
>>> station.volgende('biologie')
Station(naam='Ernst Mayr', jaar='1942', omschrijving='biologische soorten')
>>> print(station.volgende('genomica'))
Marshall Warren Nirenberg (1962, genetische code)
>>> print(station.volgende('chemie'))
Ilya Prigogine (1955, zelf-organisatie en niet-evenwicht)
>>> station.volgende('genomica').volgende('genomica')
Station(naam='Frederick Sanger', jaar='1977', omschrijving='sequencing')

>>> kaart2.uitbreiden('chemie', Station('Martin Karplus', '2013', 'computationele chemie'))
>>> kaart2.uitbreiden('informatica', Station('Martin Karplus', '2013', 'computationele chemie'))
>>> station = kaart2.eindstation('chemie')
>>> station
Station(naam='Martin Karplus', jaar='2013', omschrijving='computationele chemie')
>>> kaart2.uitbreiden('chemie', Station('Michael Levitt', '2014', 'computationele chemie'))
>>> kaart2.uitbreiden('informatica', Station('Arieh Warshel', '2014', 'computationele chemie'))
>>> station.lijnen
{'informatica': Station(naam='Arieh Warshel', jaar='2014', omschrijving='computationele chemie'), 'chemie': Station(naam='Michael Levitt', jaar='2014', omschrijving='computationele chemie')}