Atbash cipher in Python can be solved in many ways.
The first thing is to have a "key" mapping - possibly in a dict
or str.maketrans
, otherwise the value would have to be calculated on the fly.
Then, you have to "clean" up the string to be encoded by removing numbers/whitespace.
Finally, you break it up into chunks of five before returning it.
For decoding, it's similar - clean up (which automatically joins the chunks) and translate using the same key - the realization that the same key can be used is crucial in solving this in an idiomatic manner.
We use str.maketrans
to create the encoding.
In encode
, we use a generator expression in str.join
.
from string import ascii_lowercase
ENCODING = str.maketrans(ascii_lowercase, ascii_lowercase[::-1])
def encode(text: str):
res = "".join(chr for chr in text.lower() if chr.isalnum()).translate(ENCODING)
return " ".join(res[index:index+5] for index in range(0, len(res), 5))
def decode(text: str):
return "".join(chr.lower() for chr in text if chr.isalnum()).translate(ENCODING)
Read more on this approach here.
Notice that there the majority of the code is repetitive?
A fun way to solve this would be to keep it all inside the encode
function, and merely chunk it if decode
is False:
For variation, this approach shows a different way to translate the text.
from string import ascii_lowercase as asc_low
ENCODING = {chr: asc_low[id] for id, chr in enumerate(asc_low[::-1])}
def encode(text: str, decode: bool = False):
res = "".join(ENCODING.get(chr, chr) for chr in text.lower() if chr.isalnum())
return res if decode else " ".join(res[index:index+5] for index in range(0, len(res), 5))
def decode(text: str):
return encode(text, True)
For more detail, read here.