Kenneth "Kenny" McCormick is a fictional 9-year old character and one of the four main protagonists in the animated sitcom South Park1, alongside Stan Marsh2, Kyle Broflovski3, and Eric Cartman4. His often muffled and incomprehensible speech — the result of his parka hood covering his mouth — is provided by co-creator Matt Stone. Kenny is a third, later fourth-grade student who commonly has extraordinary experiences not typical of conventional small-town life in his hometown of South Park, Colorado, where he lives with his poverty-stricken family.
The character gained popularity thanks to a running gag during the first five seasons of the series, whereby Kenny would routinely suffer an excruciating death before returning alive and well in the next episode with little or no explanation. Stan would frequently use the catchphrase
Oh my god! They killed Kenny!
followed by Kyle exclaiming
You bastard(s)!
The first, only, and last time Kenny was heard speaking aloud and unmuffled was when his face was completely unconcealed in the episode Bigger, Longer & Uncut5.
Kenny's code is a pseudo-language representing the muffled voice of Kenny McCormick. The code replaces each plaintext character by a triplet (3 letters) composed of the lowercase letters m, f and p, and the uppercase letters M, F and P.
The key of Kenny's code is in a text file whose lines each consist of 4 characters: a triplet (composed of the letters M, P, F, m, p and f) followed by the corresponding plaintext character. Both the triplets and the corresponding plaintext characters are used at most once in a key of Kenny's code. With this key (kenny.01.txt6)
PPmy
FFPi
MfFe
FffK
pmPk
FMm.
mMF'
pmmh
pfpm
pFmV
FFMO
PMm
mfPl
mmMn
mFpd
FMFo
pPp$
MPFg
mpFT
mmP!
whose triplets were marked in blue, the plaintext
Oh my god! They killed Kenny!
is converted to the ciphertext
O h m y g o d ! T h e y k i l l e d K e n n y !
FFM pmm PMm pfp PPm PMm MPF FMF mFp mmP PMm mpF pmm MfF PPm PMm pmP FFP mfP mfP MfF mFp PMm Fff MfF mmM mmM PPm FMm
By replacing each triplet in the ciphertext with its corresponding plaintext character, we again obtain the plaintext.
Your task:
Write a function read_key that takes the location (str) of a text file with a key $$\mathcal{K}$$ for Kenny's code. The function must return the dictionary representation of key $$\mathcal{K}$$: a dictionary (dict) that maps each plaintext character (str) in key $$\mathcal{K}$$ onto its corresponding triplet (str).
Write a function encode that takes two arguments: i) a plaintext $$p$$ (str) and ii) the location (str) of a text file with a key $$\mathcal{K}$$ for Kenny's code. If plaintext $$p$$ has a character that does not occur in key $$\mathcal{K}$$, an AssertionError must be raised with message invalid key. Otherwise, the ciphertext (str) corresponding to plaintext $$p$$ according to Kenny's code with key $$\mathcal{K}$$ must be returned.
Write a function invert_key that takes the dictionary representation of a key $$\mathcal{K}$$ for Kenny's code. The function must return the inverse dictionary: a dictionary (dict) that maps all triplets in key $$\mathcal{K}$$ onto their corresponding plaintext character. The function may not modify the given dictionary representation of key $$\mathcal{K}$$.
Write a function decode that takes two arguments: i) a ciphertext $$c$$ (str) and ii) the location (str) of a text file with a key $$\mathcal{K}$$ for Kenny's code. If the length of ciphertext $$c$$ is not a multiple of 3 or if ciphertext $$c$$ has a triplet that does not occur in key $$\mathcal{K}$$, an AssertionError must be raised with message invalid ciphertext. Otherwise, the plaintext (str) corresponding to ciphertext $$c$$ according to Kenny's code with key $$\mathcal{K}$$ must be returned.
In the following interactive session we assume the current directory contains the text files kenny.01.txt7 and kenny.02.txt8.
>>> key = read_key('kenny.01.txt9')
>>> key['O']
'FFM'
>>> key['h']
'pmm'
>>> key[' ']
'PMm'
>>> encode('Oh my god! They killed Kenny.', 'kenny.01.txt10')
'FFMpmmPMmpfpPPmPMmMPFFMFmFpmmPPMmmpFpmmMfFPPmPMmpmPFFPmfPmfPMfFmFpPMmFffMfFmmMmmMPPmFMm'
>>> encode("Don't lie, Stan. Lying makes you sterile.", 'kenny.02.txt11')
'FfPFMfmFFPPFpmFpMMmPFfPPfpPPPfpMMFFfpmFpFFmFFpPFpMMpFfPPmfPPmFFMPfpMMMpPpFFMFffpPMMPpMMPPmFMfFpMpMMMMPpmFfpPMFPfPPmPFfpPpPF'
>>> encode('Oh my god! They killed Kenny.', 'kenny.02.txt12')
Traceback (most recent call last):
AssertionError: invalid key
>>> inverted_key = invert_key(key)
>>> inverted_key['FFM']
'O'
>>> inverted_key['pmm']
'h'
>>> inverted_key['PMm']
' '
>>> decode('FFMpmmPMmpfpPPmPMmMPFFMFmFpmmPPMmmpFpmmMfFPPmPMmpmPFFPmfPmfPMfFmFpPMmFffMfFmmMmmMPPmFMm', 'kenny.01.txt13')
'Oh my god! They killed Kenny.'
>>> decode('FfPFMfmFFPPFpmFpMMmPFfPPfpPPPfpMMFFfpmFpFFmFFpPFpMMpFfPPmfPPmFFMPfpMMMpPpFFMFffpPMMPpMMPPmFMfFpMpMMMMPpmFfpPMFPfPPmPFfpPpPF', 'kenny.02.txt14')
"Don't lie, Stan. Lying makes you sterile."
>>> decode('FFMpmmPMmpfpPPmPMmMPFFMFmFpmmPPMmmpFpmmMfFPPmPMmpmPFFPmfPmfPMfFmFpPMmFffMfFmmMmmMPPmFMm', 'kenny.02.txt15')
Traceback (most recent call last):
AssertionError: invalid ciphertext
Films with the most prolific use of the word fuck:
Tigerland16 (527×)
Nil By Mouth17 (470×)
Casino18 (422×)
South Park: Bigger, Longer & Uncut19 (399×)
Martin Lawrence Live: Runteldat20 (347×)
Another Day in Paradise21 (327×)
Summer of Sam22 (326×)
Twin Town23 (320×)
Ken Loach's Sweet Sixteen24 (313×)
Narc25 (298×)
The winner — Joel Schumacher's 2000 infantry-training drama Tigerland — packs 527 fucks into 100 minutes, for a fuck-per-minute ratio of 5.27, or one fuck every 12 seconds.
Damn it, Cantwell! Shit, man. Shit! Fuck, I don’t even know you, man! You sittin’ there telling your fucking stories. You make me want to fuckin’ cry! What’s that about?
Schumacher got a lump of coal that Christmas.