A student council has nine members. For privacy reasons, we will refer to these students with the letters A, B, …, I. Not all of the nine students are on speaking terms. This table shows which students are speaking to each other — 1 means the two students are on speaking terms and 0 means the two students are not on speaking terms.

  A B C D E F G H I
A - 0 0 1 0 0 1 0 0
B 0 - 1 1 1 1 1 1 1
C 0 1 - 0 0 0 1 1 0
D 1 1 0 - 1 0 1 0 1
E 0 1 0 1 - 0 1 0 0
F 0 1 0 0 0 - 0 0 1
G 1 1 1 1 1 0 - 0 0
H 0 1 1 0 0 0 0 - 0
I 0 1 0 1 0 1 0 0 -

Note that who speaks to whom is a symmetric relationship: if student $$x$$ speaks to student $$y$$, then student $$y$$ also speaks to student $$x$$. As a result, the table is also symmetrical: the two sections on either side of the main diagonal mirror each other. The complete relationship is therefore known if we know the values above the main diagonal (indicated in blue).

Recently student A started a rumor, and it was heard by each other student once and only once. Each student heard it from, and passed it to, another student with whom she was on speaking terms. If we count student A as zero, then student E was the eighth and last student to hear the rumor. Who was the fourth?

We know that A is at the start of the chain, and E is at the end. Of the others, F and H are each speaking to only two other students. So F must pass the rumor between B and I (in one direction or the other, BFI or IFB), and H must pass it between B and C (BHC or CHB). Putting these fragments together, we must have either CHBFI or IFBHC. Also, this larger fragment can't connect directly to either of the endpoints A or E, because neither C nor I is speaking to either of them. That means that the remaining students, D and G, must go on either end of our fragment before we can attach the endpoints. So the extended fragment is either GCHBFID or DIFBHCG, and with the endpoints A and E added we get the full chain AGCHBFIDE or ADIFBHCGE. In either case, if A is counted as zero then the fourth person is B.

Assignment

For a student council with $$n$$ students ($$2 \leq n \leq 26$$), we label the students with the first $$n$$ uppercase letters (str) of the alphabet. Your task:

You may assume that these functions only take arguments that comply with the description in the assignment, without the need to check this explicitly.

Example

This interactive session uses the student council speech table from the introduction of this assignment.

>>> table = fill_table(9, '001001001111111000110101010100001000')
>>> table
[[None, False, False, True, False, False, True, False, False], [False, None, True, True, True, True, True, True, True], [False, True, None, False, False, False, True, True, False], [True, True, False, None, True, False, True, False, True], [False, True, False, True, None, False, True, False, False], [False, True, False, False, False, None, False, False, True], [True, True, True, True, True, False, None, False, False], [False, True, True, False, False, False, False, None, False], [False, True, False, True, False, True, False, False, None]]
>>> print_table(table)
  A B C D E F G H I
A - 0 0 1 0 0 1 0 0
B 0 - 1 1 1 1 1 1 1
C 0 1 - 0 0 0 1 1 0
D 1 1 0 - 1 0 1 0 1
E 0 1 0 1 - 0 1 0 0
F 0 1 0 0 0 - 0 0 1
G 1 1 1 1 1 0 - 0 0
H 0 1 1 0 0 0 0 - 0
I 0 1 0 1 0 1 0 0 -
>>> speaks_to('A', table)
{'D', 'G'}
>>> speaks_to('B', table)
{'C', 'D', 'E', 'F', 'G', 'H', 'I'}
>>> on_speaking_terms('A', 'B', table)
False
>>> on_speaking_terms('G', 'A', table)
True
>>> is_chain('AGCHBFIDE', table)
True
>>> is_chain('ADIFBHCGE', table)
True
>>> chains('A', 'E', table)
{'ADIFBHCGE', 'AGCHBFIDE'}
>>> chains('H', 'F', table)
{'HCBEGADIF', 'HCGADEBIF'}
>>> chains('I', 'A', table)
{'IFBHCGEDA'}
>>> chains('B', 'D', table)
set()

Resources