In a tournament that works with a knockout system over $$n$$ rounds, $$2^n$$ ($$n \in \mathbb{N}$$) countries compete for the win. In each round, all remaining countries are linked to another country: the first country plays a match against the second country, the third country against the fourth country, and so on. The winner of each match advances to the next round, whereas the tournament ends for the loser. In this way, the number of countries is halved after each round, yielding a single country after $$n$$ round. That country wins the tournament.

In a knockout system, each match must yield a winner. During the ordinary time of a match, each country gets a score: the higher the score the better. If there's no winner at the end of the ordinary time, both countries can increase their score during extra time. If there's still no winner at the end of the extra time, penalties must decide who wins the match.

In the example below, for each match the score after ordinary time is indicated in yellow, and the score after extra time in gray. In this case, no match was decided by penalties.

knockout
Voorbeeld van het verloop van een toernooi tussen 8 landen, waarin wordt gewerkt met een knockoutsysteem. Voor elke wedstrijd wordt de score na de reguliere speeltijd aangegeven in het geel, en de score na de extra speeltijd in het grijs. In dit geval werd geen enkele wedstrijd beslist na het nemen van penalities.

If country $$a$$ (with capital $$c_a$$) plays a match against country $$b$$ (with capital $$c_b$$), we use a fixed procedure to determine the winner. After ordinary time, the score for country $$a$$ is equal to the number of common letters with capital $$c_b$$. Analogously, the score for country $$b$$ is equal to the number of common letters with capital $$c_a$$. This includes double letters. Some examples:

In extra time, all letters that occur on both sides are taken into account. How this works is most easily explained with a couple of examples:

With penalties, the country that comes first alphabetically wins the match. In the latter example, Australia wins on penalties against Grenada.

score
Example of the procedure to compute the score after ordinary time and after extra time, in a match between Austria (Vienna) and Lithuania (Vilnius). Lithuania wins the match after extra time.

Assignment

Write a function letter_frequencies that takes a string $$s$$ (str). The function must return a dictionary that maps each letter in $$s$$ onto its number of occurrences. The function should make no distinction between uppercase and lowercase letters in counting the number of occurrences, and the dictionary should use uppercase letters as keys. If $$s$$ contains characters that are no letters, they must be ignored.

In addition, also define a class Knockout that can be used to simulate the knockout stages of a tournament, based on the scoring procedure introduced above. The location of a CSV file1 must be passed when creating a tournament (Knockout). Each line of the file must contain the following six field with information about a country, separated by commas: i) country name, ii) capital name, iii) capital latitude, iv) capital longitude, v) country code and vi) continent name. The class Knockout must support at least the following methods:

The methods should not make a distinction between uppercase and lowercase letter when processing country names passed as argument, nor when processing capitals of these countries. If a country name that does not occur in the given CSV file is passed to one of these methods, an AssertionError must be raised with the message unknown country.

Example

In the following interactive session, we assume the CSV file countries.csv2 to be located in the current directory.

>>> letter_frequencies('Russia')
{'R': 1, 'U': 1, 'S': 2, 'I': 1, 'A': 1}
>>> letter_frequencies('Moscou')
{'M': 1, 'O': 2, 'S': 1, 'C': 1, 'U': 1}
>>> letter_frequencies('Puerto Rico')
{'P': 1, 'U': 1, 'E': 1, 'R': 2, 'T': 1, 'O': 2, 'I': 1, 'C': 1}
>>> letter_frequencies('Guinea-Bissau')
{'G': 1, 'U': 2, 'I': 2, 'N': 1, 'E': 1, 'A': 2, 'B': 1, 'S': 2}

>>> tournament = Knockout('countries.csv3')
>>> tournament.capital('Switzerland')
'Bern'
>>> tournament.capital('Estonia')
'Tallinn'
>>> tournament.ordinary_time('Switzerland', 'Estonia')
(5, 2)
>>> tournament.ordinary_time('Belgium', 'Denmark')
(2, 2)
>>> tournament.ordinary_time('Portugal', 'Austria')
(1, 2)
>>> tournament.ordinary_time('Netherlands', 'Lithuania')
(3, 3)
>>> tournament.extra_time('Belgium', 'Denmark')
(3, 2)
>>> tournament.extra_time('Netherlands', 'Lithuania')
(4, 5)
>>> tournament.match('Switzerland', 'Estonia')
'Switzerland'
>>> tournament.match('Belgium', 'Denmark')
'Belgium'
>>> tournament.match('Portugal', 'Austria')
'Austria'
>>> tournament.match('Netherlands', 'Lithuania')
'Lithuania'
>>> tournament.winner(['Switzerland', 'Estonia', 'Belgium', 'Denmark', 'Portugal', 'Austria', 'Netherlands', 'Lithuania'])
'Switzerland'