During World War II the British Special Operations Executive1 (SOE) used poetry to communicate with its agents in enemy territory. The sender and receiver would agree in advance on a poem, and by numbering its letters they produced a simple cipher that could be used to transmit messages. Because both sides could memorize the poem, there was no codebook to lose, but the Nazis could break the code fairly easily, particularly if the poem was well known.

Realizing this, SOE codes officer Leo Marks2 began to introduce original poems of his own creation. He gave this one to French agent Violette Szabo3 in March 1944:

The life that I have is all that I have,
And the life that I have is yours.
The love that I have of the life that I have
Is yours and yours and yours.

A sleep I shall have, a rest I shall have,
Yet death will be but a pause.
For the peace of my years in the long green grass
Will be yours and yours and yours.

Marks had written it three months earlier in memory of his girlfriend Ruth, who had died in a plane crash in Canada. The poem became famous when it was read in the 1958 film Carve Her Name With Pride4, about Szabo’s exploits in the war. Unfortunately, Szabo herself was captured, tortured, and killed before she could transmit any messages.

Assignment

The key of an SOE-code is derived from the text of a poem by numbering its successive letters, starting from one. Characters that are no letter are ignored while counting. Your task:

Example

In the following interactive session we assume the text file poem.txt5 to be located in the current directory.

>>> cipher = encryption('poem.txt6')
>>> cipher['C']
{177}
>>> cipher['A']
{10, 14, 19, 24, 28, 31, 43, 47, 66, 70, 84, 88, 98, 106, 114, 123, 127, 130, 138, 142, 150, 162, 164, 176, 185, 204, 218, 226}
>>> cipher['R']
{55, 96, 104, 112, 131, 170, 186, 198, 203, 216, 224, 232}
>>> cipher['K']
Traceback (most recent call last):
KeyError: 'K'

>>> reconstruct(cipher)
'THELIFETHATIHAVEISALLTHATIHAVEANDTHELIFETHATIHAVEISYOURSTHELOVETHATIHAVEOFTHELIFETHATIHAVEISYOURSANDYOURSANDYOURSASLEEPISHALLHAVEARESTISHALLHAVEYETDEATHWILLBEBUTAPAUSEFORTHEPEACEOFMYYEARSINTHELONGGREENGRASSWILLBEYOURSANDYOURSANDYOURS'

>>> encode('Carve Her Name With Pride', cipher)
[177, 176, 198, 128, 132, 9, 200, 55, 99, 47, 181, 77, 153, 26, 41, 9, 163, 232, 188, 108, 184]
>>> encode('Carve Her Name With Pride', cipher)
[177, 123, 112, 29, 173, 76, 16, 232, 195, 204, 181, 40, 153, 26, 11, 76, 119, 104, 120, 228, 173]
>>> encode('The Wind That Shakes the Barley', cipher)
[190, 42, 175, 153, 68, 227, 220, 75, 69, 19, 34, 51, 9, 164, 0, 118, 18, 41, 65, 144, 211, 130, 112, 78, 59, 93]

>>> decode([177, 176, 198, 128, 132, 9, 200, 55, 99, 47, 181, 77, 153, 26, 41, 9, 163, 232, 188, 108, 184], cipher)
'CARVEHERNAMEWITHPRIDE'
>>> decode([177, 123, 112, 29, 173, 76, 16, 232, 195, 204, 181, 40, 153, 26, 11, 76, 119, 104, 120, 228, 173], cipher)
'CARVEHERNAMEWITHPRIDE'
>>> decode([190, 42, 175, 153, 68, 227, 220, 75, 69, 19, 34, 51, 9, 164, 0, 118, 18, 41, 65, 144, 211, 130, 112, 78, 59, 93], cipher)
'THEWINDTHATSHA?ESTHEBARLEY'