Met 18 960 inwoners per km2 is Monaco het meest dichtbevolkte land van Europa, terwijl IJsland met 3.5 inwoners per km2 het meest dunbevolkt is. Om de beschikbare ruimte beter te verdelen, kunnen we een volksverhuizing organiseren door de Europese landen enerzijds te rangschikken volgens stijgend inwonersaantal en anderzijds volgens stijgende oppervlakte. Het zou dan logisch zijn om de inwoners uit het land met het kleinste inwonersaantal (Vaticaanstad) te laten verhuizen naar het land met de kleinste oppervlakte (Vaticaanstad), de inwoners uit het land met het tweede kleinste inwonersaantal (San Marino) naar het land met de tweede kleinste oppervlakte (Monaco), …, en de inwoners uit het land met het grootste inwonersaantal (Rusland) naar het land met de grootste oppervlakte (Rusland).
We zeggen dat land $$B$$ de bestemming is van land $$A$$ als de inwoners uit land $$A$$ volgens deze strategie moeten verhuizen naar land $$B$$. Op onderstaande kaart kan je de bestemmingen van alle Europese landen aflezen. Enkel de inwoners uit de blauw gemarkeerde landen (Vaticaanstad, Frankrijk en Rusland) mogen in hun eigen land blijven wonen.
Als we elk land verbinden met zijn bestemming, dan ontstaan er cirkels van landen die door de volksverhuizing een ware stoelendans uitvoeren. Bij de volksverhuizing van de Europese landen kunnen we acht dergelijke cirkels identificeren.
Een landenbestand is een tekstbestand met UTF-81 tekencodering waarvan elke regel bestaat uit een vast aantal velden met informatie over een land. De informatievelden worden van links naar rechts genummerd vanaf nul, worden van elkaar gescheiden door een tab en bevatten zelf geen tabs. Het eerste informatieveld (veld 0) bevat telkens de naam van het land. Dit zijn bijvoorbeeld enkele regels uit een landenbestand (europe.txt2) voor alle Europese landen, met naast hun naam ook nog de hoofdstad (veld 1), de bevolkingsdichtheid (veld 2; inwoners/km2), de oppervlakte (veld 3; km2) en het inwonersaantal (veld 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
Bij informatievelden die numerieke waarden bevatten, kan een punt (.) gebruikt worden als decimaal scheidingsteken en kunnen komma's (,) gebruikt worden om de duizendtallen te groeperen. Gevraagd wordt:
Schrijf een functie eigenschap waaraan de locatie (str) van een landenbestand en het volgnummer $$n \in \mathbb{N}_0$$ (int) van een numeriek informatieveld uit dat bestand moeten doorgegeven worden. De functie moet een dictionary (dict) teruggeven die de naam (str) van elk land uit het bestand afbeeldt op de corresponderende waarde (float) uit het $$n$$-de veld voor dat land.
Schrijf een functie stijgend waaraan een dictionary (dict) moet doorgegeven worden die namen (str) van landen afbeeldt op een numerieke waarde (float). De functie moet een lijst (list) teruggeven waarin de namen van de landen uit de gegeven dictionary opgelijst worden volgens stijgende numerieke waarde.
Als we in deze opgave landen in stijgende volgorde verwerken volgens één van hun numerieke eigenschappen, dan veronderstellen we steeds dat landen met dezelfde numerieke waarde voor die eigenschap verder in alfabetische volgorde verwerkt worden. Om de alfabetische volgorde te bepalen, wordt geen onderscheid gemaakt tussen hoofdletters en kleine letters.
Schrijf een functie thuisblijvers waaraan twee dictionaries $$d_{\text{van}}$$ en $$d_{\text{naar}}$$ (dict) moeten doorgegeven worden die namen (str) van dezelfde landen afbeelden op een numerieke waarde (float). De functie moet een verzameling (set) teruggeven met de namen van alle landen die twee keer op dezelfde plaats staan als we de landen oplijsten volgens stijgende numerieke waarde in $$d_{\text{van}}$$, resp. $$d_{\text{naar}}$$.
Schrijf een functie volksverhuizing waaraan twee dictionaries $$d_{\text{van}}$$ en $$d_{\text{naar}}$$ (dict) moeten doorgegeven worden die namen (str) van dezelfde landen afbeelden op een numerieke waarde (float). De functie moet een dictionary (dict) met de bestemmingen van de landen teruggeven. Daarbij moet het land met de kleinste numerieke waarde in $$d_{\text{van}}$$ afgebeeld worden op het land met de kleinste numerieke waarde in $$d_{\text{naar}}$$, het land met de tweede kleinste numerieke waarde in $$d_{\text{van}}$$ op het land met de tweede kleinste numerieke waarde in $$d_{\text{naar}}$$, …, en het land met de grootste numerieke waarde in $$d_{\text{van}}$$ op het land in de grootste numerieke waarde in $$d_{\text{naar}}$$.
Schrijf een functie cirkel waaraan twee argumenten moeten doorgegeven worden: i) de naam $$L$$ (str) van een land en ii) een dictionary $$B$$ (dict) met de bestemmingen van een aantal landen, waaronder land $$L$$. De functie moet een lijst (list) teruggeven met alle landen in de cirkel waar land $$L$$ deel van uitmaakt. De lijst begint met land $$L$$ en elk land wordt gevolgd door zijn bestemming. Het laatste land uit de lijst heeft als bestemming land $$L$$.
Schrijf een functie cirkels waaraan een dictionary (dict) met bestemmingen van een aantal landen moet doorgegeven worden. De functie moet teruggeven hoeveel (int) cirkels er zijn als we een volksverhuizing organiseren met deze bestemmingen.
In onderstaande voorbeeldsessie gaan we ervan uit dat het tekstbestand europe.txt3 zich in de huidige directory bevindt.
>>> oppervlakte = eigenschap('europe.txt4', 3)
>>> oppervlakte['Belgium']
30689.0
>>> oppervlakte['Italy']
301338.0
>>> oppervlakte['United Kingdom']
242495.0
>>> stijgend(oppervlakte)
['Vatican City', 'Monaco', 'San Marino', 'Liechtenstein', 'Malta', 'Andorra', 'Luxembourg', 'Cyprus', 'Kosovo', 'Montenegro', 'Slovenia', 'North Macedonia', 'Albania', 'Belgium', 'Moldova', 'Switzerland', 'Netherlands', 'Denmark', 'Estonia', 'Slovakia', 'Bosnia and Herzegovina', 'Croatia', 'Latvia', 'Lithuania', 'Ireland', 'Czech Republic', 'Austria', 'Portugal', 'Hungary', 'Serbia', 'Iceland', 'Bulgaria', 'Greece', 'Belarus', 'Romania', 'United Kingdom', 'Italy', 'Poland', 'Finland', 'Germany', 'Norway', 'Sweden', 'Spain', 'France', 'Ukraine', 'Russia']
>>> inwoners = eigenschap('europe.txt5', 4)
>>> inwoners['Belgium']
11515793.0
>>> inwoners['Italy']
60404355.0
>>> inwoners['United Kingdom']
66040229.0
>>> stijgend(inwoners)
['Vatican City', 'San Marino', 'Liechtenstein', 'Monaco', 'Andorra', 'Iceland', 'Malta', 'Luxembourg', 'Montenegro', 'Cyprus', 'Estonia', 'Kosovo', 'Latvia', 'Slovenia', 'North Macedonia', 'Moldova', 'Lithuania', 'Albania', 'Bosnia and Herzegovina', 'Croatia', 'Ireland', 'Norway', 'Slovakia', 'Finland', 'Denmark', 'Serbia', 'Bulgaria', 'Switzerland', 'Austria', 'Belarus', 'Hungary', 'Sweden', 'Portugal', 'Czech Republic', 'Greece', 'Belgium', 'Netherlands', 'Romania', 'Poland', 'Ukraine', 'Spain', 'Italy', 'United Kingdom', 'France', 'Germany', 'Russia']
>>> thuisblijvers(inwoners, oppervlakte)
{'France', 'Russia', 'Vatican City'}
>>> bestemming = volksverhuizing(inwoners, oppervlakte)
>>> bestemming['Belgium']
'United Kingdom'
>>> bestemming['Italy']
'Sweden'
>>> bestemming['United Kingdom']
'Spain'
>>> cirkel('Albania', bestemming)
['Albania', 'Denmark', 'Ireland', 'Bosnia and Herzegovina', 'Estonia', 'Slovenia', 'Belgium', 'United Kingdom', 'Spain', 'Norway', 'Croatia', 'Slovakia', 'Latvia']
>>> cirkel('Andorra', bestemming)
['Andorra', 'Malta', 'Luxembourg', 'Cyprus', 'Montenegro', 'Kosovo', 'North Macedonia', 'Moldova', 'Switzerland', 'Portugal', 'Greece', 'Romania', 'Poland', 'Finland', 'Lithuania', 'Netherlands', 'Italy', 'Sweden', 'Bulgaria', 'Austria', 'Hungary', 'Iceland']
>>> cirkel('Belarus', bestemming)
['Belarus', 'Serbia', 'Czech Republic']
>>> cirkel('France', bestemming)
['France']
>>> cirkel('Germany', bestemming)
['Germany', 'Ukraine']
>>> cirkel('Liechtenstein', bestemming)
['Liechtenstein', 'San Marino', 'Monaco']
>>> cirkel('Russia', bestemming)
['Russia']
>>> cirkel('Vatican City', bestemming)
['Vatican City']
>>> cirkels(bestemming)
8