In its 2011 November issue, NWT Magazine published the Underground map of Science below. The challenge of this assignment consists of adding new data types to Python that allow to construct, expand and question such underground maps. An underground map is built from a number of underground lines that link different stations in a set order The traffic on an underground line goes in only one direction, and for this assignment, underground lines never form a loop. Some stations can be on multiple underground lines, so that it is possible to transfer from one line to another.
Define a class Station with which the underground stations can be represented on a map. Every underground station possesses the properties name, year and description, that each represent a string (the year can also be described as for example: 6th century BC). From every station you can go to zero or more other metro stations, but each of these outgoing connections are on a different underground line. To represent these outgoing connections, every station possesses a property lines that refers to a dictionary. This dictionary prints the underground lines that leave from a station, by portraying each name of a line (a string; here always the name of a science) on the following line.
The objects of the class Station must possess at least the following methods:
An initializing method __init__ with at least three parameters: name, year and description. Three strings must be given to these parameters, that each must be appointed to the properties of the same name of the newly constructed object. Furthermore, every newly constructed object should also possess a property lines that initially refers to an empty dictionary.
A method __eq__ that can be used to test whether two underground stations are equal. Two stations are only seen as equal if the values of their properties name, year and description are equal. Do note that the values of the property lines has no influence on the equality of underground stations.
A method __repr__ that prints a string representation of the underground stationd of the format Station(name=name, year=year, description=description). Here, name, year and description must respectively be filled out with the string representation of the properties name, year and description of the object.
A method __str__ that prints the string representation of the underground station in the format name (year, description). Here, name, year and description must respectively be filled out with the value of the properties name, year and description of the object.
A method link that can be used to link an underground station on a given underground line with another station (an object of the class Station). The name of the underground line and the other underground station with which the link is made, must be given to the method as arguments. The method must raise an AssertionError with the message station is already linked with line name if the station already has an outgoing connection for the given underground line. Here, instead of name in the message, the name of the underground line should appear.
A method next to which the name of an underground line must be given. The method must print the station with which the underground station is linked on the given line. If the station on the given line is not connected with any other stations, the method should print the value None.
Define a class UndergroundMap with which underground maps can be represented. Underground maps are built from a number of underground lines that connect various stations in a set order. Every underground map possesses a property lines, that refers to a dictionary. This dictionary portrays the name (a string; here always the name of a science) for every underground line on the map on the begin station of the underground line (an object of the class Station). The objects of the class UndergroundMap must at least contain the following methods:
An initializing method __init__ that makes sure that every newly constructed underground map has a property lines that initially refers to an empty dictionary.
A method beginstation that prints the begin station (an object from the class Station) of a given underground line. The name of the underground line must be given to the function as an argument. If the underground map does not contain a line of the given name, the method should print the value None.
A method terminal that prints the terminal (an object of the class Station) of a given underground line. The name of the line must be given to the function as an argument. If the underground map does not contain a line of the given name, the method must print the value None.
A method expand which
can be used to expand a given underground line with a new station. The
name of the line and the new station (an object of the class Station)
must be given to the method as arguments. Expanding an underground line
is done by linking the terminal of the line with the new station. If the
underground map does not yet contain a line with the given name, the new
station should be the begin station of the line. But be careful: a map
may never contain two stations with the same name. If the map already
has a station with the same name of the new station, the terminal of the
given line must be linked with the station that already exists. Suppose
the situation below where line1
already has a station with the name B,
and we want to expand line2
(with terminal C) with a
station named B. Then
station C must be linked
with the existing station (indicated in green) and no new station should
be added to the map (indicated in red).
A method addStations to which a location of a text file must be given. Every line of this file must contain the four following fields, separated by a single tab: i) the name of a science, ii) the name of a scientist, iii) a year and iv) a short description of important accomplishments of the scientist. The method must expand for every line indicated with the underground line with the name of a science, with a station of which the name, the year and the description are based on the last three fields. These expansions must happen in the order in which the lines occur in the file.
Make sure that the initializing method has an optional parameter stations, to which the location of a text file can be given. If a value is given to this parameter, the map must already be expanded with the order and description of the stations like they are in the text file in the initialization. You do this of course by calling the method addStations.
Make sure you use the methods you have already implemented optimally when implementing the classes Station and UndergroundMap.
>>> station1 = Station('James Watson', '1953', 'clarification DNA-structure')
>>> station1.name
'James Watson'
>>> station1.year
'1953'
>>> station1.description
'clarification DNA-structure'
>>> station1.lines
{}
>>> station1 == station1
True
>>> station1
Station(name='James Watson', year='1953', description='clarification DNA-structure')
>>> station2 = Station(name='Ernst Mayr', year='1942', description='biological species')
>>> print(station2)
Ernst Mayr (1942, biological species)
>>> station1 == station2
False
>>> station1.link('biology', station2)
>>> station1.lines
{'biology': Station(name='Ernst Mayr', year='1942', description='biological species')}
>>> station1.next('biology')
Station(name='Ernst Mayr', jaar='1942', description='biological species')
>>> print(station1.next('chemistry'))
None
>>> station3 = Station('Marshall Warren Nirenberg', '1962', 'genetic code')
>>> station4 = Station('Ilya Prigogine', '1955', 'self-organization and non-balance')
>>> station1.link('chemistry', station3)
>>> station1.link('chemistry', station4)
Traceback (most recent call last):
AssertionError: station is already linked with line chemistry
>>> station1.link('genomics', station4)
>>> station1.lines
{'biologie': Station(name='Ernst Mayr', yearr='1942', description='biological species'), 'genomics': Station(name='Ilya Prigogine', year='1955', description='self-organization and non-balance'), 'chemistry': Station(name='Marshall Warren Nirenberg', year='1962', description='genetic code')}
>>> print(station1.next('chemistry'))
Marshall Warren Nirenberg (1962, genetic code)
>>> print(station1.next('genomics'))
Ilya Prigogine (1955, self-organization and non-balance)
In the example session below we assume that the text file milestones.txt1 is situated in the current directory.
>>> metromap = Metrokaart()
>>> metromap.expand('genomics', Station('James Watson', '1953', 'clarification DNA-structure'))
>>> metromap.expand('genomics', Station('Marshall Warren Nirenberg', '1962', 'genetic code'))
>>> metromap.expand('genomics', Station(name='Frederick Sanger', year='1977', description='sequencing'))
>>> metromap.beginstation('genomics')
Station(naam='James Watson', year='1953', description='clarification DNA-structure')
>>> metromap.terminal('genomics')
Station(name='Frederick Sanger', year='1977', description='sequencing')
>>> metromap.expand('chemistry', Station('Robert Boyle', '1661', 'The Sceptical Chymist'))
>>> metromap.beginstation('chemistry')
Station(name='Robert Boyle', year='1661', description='The Sceptical Chymist')
>>> metromap.terminal('chemistry')
Station(name='Robert Boyle', year='1661', description='The Sceptical Chymist')
>>> metromap2 = Undergroundmetromap('milestones.txt')
>>> metromap2.beginstation('chemistry')
Station(name='Robert Boyle', year='1661', description='The Sceptical Chymist')
>>> metromap2.terminal('chemistry')
Station(name='Paul Crutzen', year='1985', description='atmospheric chemistry')
>>> station = metromap2.beginstation('genomics')
>>> station
Station(name='James Watson', year='1953', description='clarification DNA-structure')
>>> station.next('biology')
Station(name='Ernst Mayr', year='1942', description='biological species')
>>> print(station.next('genomics'))
Marshall Warren Nirenberg (1962, genetic code)
>>> print(station.next('chemistry'))
Ilya Prigogine (1955, self-organization and non-balance)
>>> station.next('genomics').next('genomics')
Station(name='Frederick Sanger', year='1977', description='sequencing')
>>> metromap2.expand('chemistry', Station('Martin Karplus', '2013', 'computational chemistry'))
>>> metromap2.expand('informatics', Station('Martin Karplus', '2013', 'computational chemistry'))
>>> station = metromap2.terminal('chemistry')
>>> station
Station(name='Martin Karplus', year='2013', description='computational chemistry')
>>> metromap2.expand('chemistry', Station('Michael Levitt', '2014', 'computational chemistry'))
>>> metromap2.expand('informatics', Station('Arieh Warshel', '2014', 'computational chemistry'))
>>> station.lines
{'informatics': Station(name='Arieh Warshel', year='2014', description='computational chemistry'), 'chemistry': Station(name='Michael Levitt', year='2014', description='computational chemistry')}