In 1984, German painter and artist Ralf Krempel obtained a patent for encoding messages as color codes. Each character is encoded as a unique sequence of one or more colors. According to the following table, uppercase letter C is encoded as color code yellow-blue, lowercase letter o as color code blue, and lowercase letter s as color code red-yellow.

To encode a plaintext, join the color codes for its characters, separated by a black color. Using the above color codes, plaintext Cosmopolitan is encoded into this ciphertext.

A modern version of the Krempel code represents each color in the ciphertext by an emoji of that color. As there are multiple emojis of the same color, each color can be represented by different emojis.

If we represent each color in the ciphertext for Cosmopolitan with a randomly chosen emoji of that color, we may get this ciphertext.

As each color is represented by a randomly chosen emoji of that color, this could be an alternative ciphertext for Cosmopolitan.

We simply reverse the process to decode a ciphertext. If the ciphertext is represented by emojis, we first determine the color for each emoji. Then we determine the corresponding character for each color code — with color codes separated from each other by a black color. The plaintext is obtained by concatenating these characters.
To encode and decode messages according to a Krempel code, we represent each color in the ciphertext by a unique uppercase letter (str). The color black is always represented by an asterisk (*; str).
The color codes for a Krempel code are defined in a text file. Each line of the file consists of a character that can occur in a plaintext, followed by one or more uppercase letters that represent the color code for the character in a ciphertext. For example, these are the first few lines of the file with color codes for the Krempel code we used in the introduction (krempel.txt):
AYG
aGB
BGR
CYB
iGP
JRR
KY
LYP
lP
mRB
nYR
OG
…
Using these color codes, the ciphertext (str) for Cosmopolitan is
YB*B*RY*RB*B*YY*B*P*GP*GY*GB*YR
We can also represent a color using an emoji (str) from the UTF-8 character encoding, where emojis are a single character. Multiple emojis could represent the same color, unlike uppercase letters and the asterisk that always represent a color in a unique way.
The colors of emojis for a Krempel code are defined in a text file. Each line of the file consists of an emoji and the uppercase letter or an asterisk (*) for the color of that emoji. For example, these are the first few lines of the file with emojis for the Krempel code we used in the introduction (emoji.txt):
πR
π§B
πY
πP
π«G
πG
π€*
πP
πY
π’G
π₯©R
πP
…
Using these emojis, the ciphertext (str) for Cosmopolitan can be represented as (first example from introduction)
ππ¦π¦π§π€πππ€πππ¦π¦π€πππ¦π¦π€πΎπ€π«ππ¦πππ€π’ππ€ππ
or as (second example from introduction)
πππ¦π§π¦π₯©ππ€πππ€ππ¦πππ¦π¬π€πΎπ¦π«ππ€π«ππ€π’π¦π€ππ₯©
Define a class Krempel that can be used to encode and decode messages according to a Krempel code. When creating a new Krempel code (Krempel), the location (str) of a text file containing the color codes used by the Krempel code must be passed. Optionally, a second argument can be passed: the location (str) of a text file containing the emojis used by the Krempel code. If no second argument is passed, the Krempel code does not use emojis.
A Krempel code $$\mathcal{K}$$ must support at least the following methods:
A method character2code that takes a character (str). If Krempel code $$\mathcal{K}$$ does not support the character in plaintext, the method must raise an AssertionError with message invalid character. Otherwise, the method must return the ciphertext color code (str) corresponding with that plaintext character according to Krempel code $$\mathcal{K}$$.
A method code2character that takes a color code (str). If Krempel code $$\mathcal{K}$$ does not support the color code in ciphertext, the method must raise an AssertionError with message invalid code. Otherwise, the method must return the plaintext character (str) corresponding with that ciphertext color code according to Krempel code $$\mathcal{K}$$.
A method uses_emojis that takes no arguments. The methode must return a Boolean value (bool), indicating whether Krempel code $$\mathcal{K}$$ uses emojis in ciphertext.
A method emoji2color that takes an emoji (str). If Krempel code $$\mathcal{K}$$ uses no emojis in ciphertext, the method must raise an AssertionError with message Krempel code uses no emojis. If Krempel code $$\mathcal{K}$$ does not support the emoji in ciphertext, the method must raise an AssertionError with message invalid emoji. Otherwise, the method must return the color (str) of that emoji according to Krempel code $$\mathcal{K}$$.
A method color2emoji that takes a color (str). If Krempel code $$\mathcal{K}$$ uses no emojis in ciphertext, the method must raise an AssertionError with message Krempel code uses no emojis. If Krempel code $$\mathcal{K}$$ does not associate emojis with the color, the method must raise an AssertionError with message invalid color. Otherwise, the method must return a randomly chosen emoji (str) of that color according to Krempel code $$\mathcal{K}$$.
In Python, you cannot directly select a random element from a set. You can do this by first converting the set to a sequence (list or tuple) and then selecting a random element from the sequence.
A method decode that takes a ciphertext $$c$$ encoded according to Krempel code $$\mathcal{K}$$ (str). If Krempel code $$\mathcal{K}$$ does not use emojis, the colors of ciphertext $$c$$ must be represented with uppercase letters and asterisks (*). Otherwise, the colors in ciphertext $$c$$ must be represented with emojis. The method must return the plaintext (str) obtained by decoding ciphertext $$c$$ (str) according to Krempel code $$\mathcal{K}$$.
A method encode that takes a plaintext $$t$$ (str). The method must return the ciphertext (str) obtained by encoding plaintext $$t$$ according to Krempel code $$\mathcal{K}$$. If Krempel code $$\mathcal{K}$$ does not use emojis, the colors in the ciphertext must be represented with uppercase letters and asterisks (*). Otherwise, each color in the ciphertext must be represented by a randomly chosen emoji of that color.
In this interactive session, we assume the text files krempel.txt and emoji.txt to be located in the current directory.
>>> krempel_01 = Krempel('krempel.txt')
>>> krempel_01.character2code('C')
'YB'
>>> krempel_01.character2code('?')
Traceback (most recent call last):
AssertionError: invalid character
>>> krempel_01.code2character('YB')
'C'
>>> krempel_01.code2character('BY')
Traceback (most recent call last):
AssertionError: invalid code
>>> krempel_01.uses_emojis()
False
>>> krempel_01.emoji2color('π')
Traceback (most recent call last):
AssertionError: Krempel code uses no emojis
>>> krempel_01.color2emoji('Y')
Traceback (most recent call last):
AssertionError: Krempel code uses no emojis
>>> krempel_01.decode('YB*B*RY*RB*B*YY*B*P*GP*GY*GB*YR')
'Cosmopolitan'
>>> krempel_01.encode('Cosmopolitan')
'YB*B*RY*RB*B*YY*B*P*GP*GY*GB*YR'
>>> krempel_02 = Krempel('krempel.txt', 'emoji.txt')
>>> krempel_02.uses_emojis()
True
>>> krempel_02.emoji2color('π')
'Y'
>>> krempel_02.emoji2color('π€’')
Traceback (most recent call last):
AssertionError: invalid emoji
>>> krempel_02.color2emoji('Y')
'π'
>>> krempel_02.color2emoji('X')
Traceback (most recent call last):
AssertionError: invalid color
>>> krempel_02.decode('ππ¦π¦π§π€πππ€πππ¦π¦π€πππ¦π¦π€πΎπ€π«ππ¦πππ€π’ππ€ππ')
'Cosmopolitan'
>>> krempel_02.decode('πππ¦π§π¦π₯©ππ€πππ€ππ¦πππ¦π¬π€πΎπ¦π«ππ€π«ππ€π’π¦π€ππ₯©')
'Cosmopolitan'
>>> krempel_02.encode('Cosmopolitan')
'ππ¦π¦π§π€πππ€πππ¦π¦π€πππ¦π¦π€πΎπ€π«ππ¦πππ€π’ππ€ππ'
>>> krempel_02.encode('Cosmopolitan')
'πππ¦π§π¦π₯©ππ€πππ€ππ¦πππ¦π¬π€πΎπ¦π«ππ€π«ππ€π’π¦π€ππ₯©'