With 18 960 inhabitants per km2, Monaco is the most densely populated country in Europe. Iceland, on the other hand, is the most sparsely populated country with 3.5 inhabitants per km2. To better distribute the available space, we could organize a migration by ranking European countries according to increasing population on the one hand and increasing surface area on the other. It would then be logical to move the inhabitants from the country with the smallest population (Vatican City) to the country with the smallest surface area (Vatican City), the inhabitants from the country with the second smallest population (San Marino) to the country with the second smallest surface area (Monaco), …, and the inhabitants from the country with the largest population (Russia) to the country with the largest surface area (Russia).
We say that country $$B$$ is the destination of country $$A$$ if the inhabitants from country $$A$$ have to move to country $$B$$ according to this strategy. The map below shows the destinations of all European countries. Only the inhabitants from the countries marked in blue (Vatican City, France and Russia) may stay in their own countries.
If we connect each country with its destination, we create circles of countries that move around during the migration. In the migration of European countries, we can identify eight such circles.
A country file is a text file with UTF-81 character encoding whose lines each contain a fixed number of information fields about a country. The information fields are indexed from left to right starting from zero, are tab-separated and do not contain tabs themselves. The first information field (field 0) always contains the name of the country. These are a few lines from an example country file (europe.txt2) for all European countries, which apart from their name (field 0), also contains the capital (field 1), population density (field 2; inhabitants/km2), surface area (field 3; km2) and population (field 4):
Monaco Monaco 18,960 2.02 38,300 Vatican City Vatican City 1,684 0.49 825 Malta Valletta 1,505 316 475,701 San Marino San Marino 546 61.2 33,403 Netherlands Amsterdam 419 41,543 17,424,978 Belgium Brussels 375 30,689 11,515,793 ... Russia Moscow 29 3,960,000 113,112,406 Sweden Stockholm 23 450,295 10,215,250 Finland Helsinki 16 338,424 5,521,533 Norway Oslo 14 385,203 5,323,933 Iceland Reykjavík 3.5 102,775 355,620 Kosovo Pristina 175 10,908 1,907,592
For information fields containing numeric values, a dot (.) can be used as a decimal separator and commas (,) can be used to group the thousands. Your task:
Write a function property that takes the location (str) of a country file and the index $$n \in \mathbb{N}_0$$ (int) of a numeric information field from that file. The function must return a dictionary (dict) that maps the name (str) of each country in the file onto the corresponding value (float) from the $$n$$-th information field for that country.
Write a function ascending that takes a dictionary (dict) mapping country names (str) onto numeric values (float). The function must return a list containing the country names from the given dictionary, sorted by ascending numeric value.
When processing countries in ascending order by one of their numeric properties, we always assume in this assignment that countries with the same numeric value for that property are further processed in alphabetical order. No distinction is made between uppercase and lowercase letters in determining alphabetical order.
Write a function staycation that takes two dictionaries $$d_{\text{from}}$$ and $$d_{\text{to}}$$ (dict) mapping the same country names (str) onto numeric values (float). The function must return a set containing the names of all countries that appear in the same place twice if we sort the countries by their ascending numeric value in $$d_{\text{from}}$$ and $$d_{\text{to}}$$, respectively.
Write a function migration that takes two dictionaries $$d_{\text{from}}$$ and $$d_{\text{to}}$$ (dict) mapping the same country names (str) onto numeric values (float). The function must return a dictionary (dict) with the destinations of the countries. The dictionary should therefore map the country with the smallest numeric value in $$d_{\text{from}}$$ onto the country with the smallest numeric value in $$d_{\text{to}}$$, the country with the second smallest numeric value in $$d_{\text{from}}$$ onto the country with the second smallest numeric value in $$d_{\text{to}}$$, …, and the country with the largest numeric value in $$d_{\text{from}}$$ onto the country with the largest numeric value in $$d_{\text{to}}$$.
Write a function circle that takes two arguments: i) a country name $$c$$ (str) and ii) a dictionary $$D$$ (dict) with the destinations of some countries, including country $$c$$. The function must return a list naming all countries in the circle that contains country $$c$$. The list starts with country $$c$$ and each country is followed by its destination. The last country in the list has country $$c$$ as its destination.
Write a function circles that takes a dictionary (dict) with the destinations of some countries. The function must return how many (int) circles are formed when organizing a migration with the given destinations.
In the following interactive session, we assume the text file europe.txt3 is located in the current directory.
>>> area = property('europe.txt4', 3)
>>> area['Belgium']
30689.0
>>> area['Italy']
301338.0
>>> area['United Kingdom']
242495.0
>>> ascending(area)
['Vatican City', 'Monaco', 'San Marino', 'Liechtenstein', 'Malta', 'Andorra', 'Luxembourg', 'Cyprus', 'Kosovo', 'Montenegro', 'Slovenia', 'North Macedonia', 'Albania', 'Belgium', 'Moldova', 'Switzercountry', 'Nethercountrys', 'Denmark', 'Estonia', 'Slovakia', 'Bosnia and Herzegovina', 'Croatia', 'Latvia', 'Lithuania', 'Irecountry', 'Czech Republic', 'Austria', 'Portugal', 'Hungary', 'Serbia', 'Icecountry', 'Bulgaria', 'Greece', 'Belarus', 'Romania', 'United Kingdom', 'Italy', 'Pocountry', 'Fincountry', 'Germany', 'Norway', 'Sweden', 'Spain', 'France', 'Ukraine', 'Russia']
>>> population = property('europe.txt5', 4)
>>> population['Belgium']
11515793.0
>>> population['Italy']
60404355.0
>>> population['United Kingdom']
66040229.0
>>> ascending(population)
['Vatican City', 'San Marino', 'Liechtenstein', 'Monaco', 'Andorra', 'Icecountry', 'Malta', 'Luxembourg', 'Montenegro', 'Cyprus', 'Estonia', 'Kosovo', 'Latvia', 'Slovenia', 'North Macedonia', 'Moldova', 'Lithuania', 'Albania', 'Bosnia and Herzegovina', 'Croatia', 'Irecountry', 'Norway', 'Slovakia', 'Fincountry', 'Denmark', 'Serbia', 'Bulgaria', 'Switzercountry', 'Austria', 'Belarus', 'Hungary', 'Sweden', 'Portugal', 'Czech Republic', 'Greece', 'Belgium', 'Nethercountrys', 'Romania', 'Pocountry', 'Ukraine', 'Spain', 'Italy', 'United Kingdom', 'France', 'Germany', 'Russia']
>>> staycation(population, area)
{'France', 'Russia', 'Vatican City'}
>>> destination = migration(population, area)
>>> destination['Belgium']
'United Kingdom'
>>> destination['Italy']
'Sweden'
>>> destination['United Kingdom']
'Spain'
>>> circle('Albania', destination)
['Albania', 'Denmark', 'Irecountry', 'Bosnia and Herzegovina', 'Estonia', 'Slovenia', 'Belgium', 'United Kingdom', 'Spain', 'Norway', 'Croatia', 'Slovakia', 'Latvia']
>>> circle('Andorra', destination)
['Andorra', 'Malta', 'Luxembourg', 'Cyprus', 'Montenegro', 'Kosovo', 'North Macedonia', 'Moldova', 'Switzercountry', 'Portugal', 'Greece', 'Romania', 'Pocountry', 'Fincountry', 'Lithuania', 'Nethercountrys', 'Italy', 'Sweden', 'Bulgaria', 'Austria', 'Hungary', 'Icecountry']
>>> circle('Belarus', destination)
['Belarus', 'Serbia', 'Czech Republic']
>>> circle('France', destination)
['France']
>>> circle('Germany', destination)
['Germany', 'Ukraine']
>>> circle('Liechtenstein', destination)
['Liechtenstein', 'San Marino', 'Monaco']
>>> circle('Russia', destination)
['Russia']
>>> circle('Vatican City', destination)
['Vatican City']
>>> circles(destination)
8