In haar Novembernummer van 2011 publiceerde NWT Magazine1 onderstaande Metrokaart der exacte wetenschap. De uitdaging van deze opgave bestaat erin om nieuwe gegevenstypes aan JavaScript 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.
Definieer een klasse Station waarmee de metrostations op een metrokaart kunnen voorgesteld worden. Bij het aanmaken van een niuew metrostation (Station) moeten drie strings (String) doorgegeven worden die respectievelijk de naam, het jaartal van oprichting en een korte omschrijving van het metrostation aanduiden (het jaartal kan ook beschreven worden door bv. 6e eeuw v. Chr.). Deze argumenten moeten respectievelijk toegekend worden aan de attributen naam, jaar en omschrijving van het nieuw aangemaakte metrostation (Station).
Vanuit elk metrostation kan je vertrekken naar nul of meer andere metrostations, maar elk van deze uitgaande verbindingen liggen op een verschillende metrolijn. Hierdoor kan een metrostation (Station) schematisch voorgesteld worden als:
Voorts moeten op een metrostation $$s$$ (Station) minstens de volgende methoden kunnen aangeroepen worden:
Een methode toString waaraan geen argumenten moeten doorgegeven worden. De methode moet een stringvoorstelling (String) van metrostation $$s$$ teruggeven volgens het formaat naam (jaar, omschrijving). Hierbij moeten naam, jaar en omschrijving respectievelijk ingevuld worden met de waarde van de eigenschappen naam, jaar en omschrijving van metrostation $$s$$.
Een methode verbind die kan gebruikt worden om metrostation $$s$$ op een gegeven metrolijn te verbinden met een ander metrostation $$t$$. Hierdoor wordt $$t$$ het metrostation dat op de gegeven metrolijn volgt op metrostation $$s$$. De naam van de metrolijn (String) en het metrostation $$t$ (Station) waarmee de verbinding moet gemaakt worden, moeten als argumenten aan de methode doorgegeven worden. De methode moet een Error opwerpen met de boodschap station is reeds verbonden op lijn naam indien metrostation $$s$$ reeds een uitgaande verbinding heeft voor de metrolijn met de gegeven naam. Hierbij moet op de plaats van naam in de boodschap uiteraard de gegeven naam van de metrolijn ingevuld worden.
Een methode metrolijnen waaraan geen argumenten moeten doorgegeven worden. De methode moet een reeks (Array) teruggeven met de lexicografisch gesorteerde namen (String) van alle metrolijnen waarop je nog verder kan reizen vanaf metrostation $$s$$.
Een methode volgende waaraan de naam van een metrolijn (String) moet doorgegeven worden. De methode moet het metrostation (Station) teruggeven waarmee metrostation $$s$$ verbonden is op de gegeven metrolijn. Als metrostation $$s$$ op de gegeven metrolijn niet verbonden is met een ander metrostation, dan moet de waarde undefined teruggegeven worden.
> const station1 = new Station("James Watson", "1953", "opheldering DNA-structuur")
> station1.naam
"James Watson"
> station1.jaar
"1953"
> station1.omschrijving
"opheldering DNA-structuur"
> station1.toString()
"James Watson (1953, opheldering DNA-structuur)"
> station1.metrolijnen()
[]
> const station2 = new Station("Ernst Mayr", "1942", "biologische soorten")
> station2.toString()
"Ernst Mayr (1942, biologische soorten)"
> station1.verbind("biologie", station2)
> station1.metrolijnen()
["biologie"]
> station1.volgende("biologie").toString()
"Ernst Mayr (1942, biologische soorten)"
> station1.volgende("chemie")
> const station3 = new Station("Marshall Warren Nirenberg", "1962", "genetische code")
> const station4 = new Station("Ilya Prigogine", "1955", "zelf-organisatie en niet-evenwicht")
> station1.verbind("chemie", station3)
> station1.verbind("chemie", station4)
Error: station is reeds verbonden op lijn chemie
> station1.verbind("genomica", station4)
> station1.metrolijnen()
["biologie", "chemie", "genomica"]
> station1.volgende("chemie").toString()
"Marshall Warren Nirenberg (1962, genetische code)"
> station1.volgende("genomica").toString()
"Ilya Prigogine (1955, zelf-organisatie en niet-evenwicht)"
Definieer ook nog 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. Bij het aanmaken van een nieuwe metrokaart (Metrokaart) moeten geen argumenten doorgegeven worden. Op een metrokaart $$k$$ (Metrokaart) moeten minstens de volgende methoden kunnen aangeroepen worden:
Een methode beginstation die het beginstation (Station) van een gegeven metrolijn op metrokaart $$k$ teruggeeft. De naam van de metrolijn (String) moet als argument aan de functie doorgegeven worden. Als metrokaart $$k$$ geen metrolijn heeft met de gegeven naam, dan moet de waarde undefined teruggegeven worden.
Een methode eindstation die het eindstation (Station) van een gegeven metrolijn op metrokaart $$k$ teruggeeft. De naam van de metrolijn (String) moet als argument aan de functie doorgegeven worden. Als metrokaart $$k$$ geen metrolijn heeft met de gegeven naam, dan moet de waarde undefined teruggegeven worden.
Een methode uitbreiden waarmee een gegeven metrolijn op metrokaart $$k$$ kan uitgebreid worden met een nieuw metrostation $$t$$. De naam van de metrolijn (String) en het metrostation $$t$$ (Station) moeten als argumenten aan de methode doorgegeven worden. Het uitbreiden van een metrolijn gebeurt door het eindstation $$s$$ van de metrolijn te verbinden met metrostation $$t$$. Als metrokaart $$k$$ nog geen metrolijn bevatte met de gegeven naam, dan moet metrostation $$t$$ het beginstation van de metrolijn worden.
Maar let op: een metrokaart mag nooit twee metrostations met dezelfde naam bevatten. Als de metrokaart reeds een metrostation $$t'$$ heeft met dezelfde naam als metrostation $$t$$, dan moet het eindstation $$s$$ van de gegeven metrolijn verbonden worden met $$t'$$ en niet met $$t$$. Hierbij gaan we ervan uit dat alle metrostations aan de metrokaart toegevoegd worden via de methode uitbreiden.
Veronderstel onderstaande situatie waarbij op lijn1 reeds een metrostation voorkomt met naam B, en we lijn2 (met eindstation C) willen uitbreiden met een metrostation met naam B. Dan moet metrostation C verbonden worden met het bestaande metrostation (hier aangeven in het groen) en moet er geen nieuw metrostation aan de metrokaart toegevoegd worden (hier aangegeven in het rood).
Een methode metrolijn waaraan de naam van een metrolijn (String) moet doorgegeven worden. De methode moet een reeks (Array) teruggeven met alle namen (String) van de stations op de gegeven metrolijn, in de volgorde waarin de stations voorkomen op die metrolijn. Als de metrokaart geen metrolijn bevat met de gegeven naam, dan moet een lege reeks (Array) teruggegeven worden.
> const kaart = new Metrokaart()
> kaart.uitbreiden("genomica", new Station("James Watson", "1953", "opheldering DNA-structuur"))
> kaart.uitbreiden("genomica", new Station("Marshall Warren Nirenberg", "1962", "genetische code"))
> kaart.uitbreiden("genomica", new Station("Frederick Sanger", "1977", "sequencing"))
> kaart.beginstation("genomica").toString()
"James Watson (1953, opheldering DNA-structuur)"
> kaart.eindstation("genomica").toString()
"Frederick Sanger (1977, sequencing)"
> kaart.metrolijn("genomica")
["James Watson", "Marshall Warren Nirenberg", "Frederick Sanger"]
> kaart.uitbreiden("chemie", new Station("Robert Boyle", "1661", "The Sceptical Chymist"))
> kaart.beginstation("chemie").toString()
"Robert Boyle (1661, The Sceptical Chymist)"
> kaart.eindstation("chemie").toString()
"Robert Boyle (1661, The Sceptical Chymist)"
> kaart.metrolijn("chemie")
["Robert Boyle"]