I have a few lines of code for making a rotated string for a Caesar cipher and just for fun I am trying to condense them into one. Obviously this is pointless since it is completely unreadable but I'm curious. Still, I can't quite figure out how to do it. Here's what I have tried so far
s = 'abcdefghijklmnopqrstuvwxyz'
rot = raw_input('Enter Rotation or Key: ')
s = s[-int(rot):] + s[:-int(rot)] if rot.isdigit() else rot.lower()+ ''.join([j for i in s for j in rot.lower() if j == i]) # This is the only line I want condensed
print s
Here is the readable version which actually works
s = 'abcdefghijklmnopqrstuvwxyz'
rot = raw_input('Enter Rotation or Key: ')
if rot.isdigit(): #I only want from here
s = s[-int(rot):] + s[:-int(rot)]
else:
for i in rot.lower():
s = s.replace(i,'')
s = rot.lower() + s #To here condensed into one line
print s
rot
is the amount to rotate the alphabet or the key for a keyed version of a Caesar cipher. You should be able to just run the code as is and see exactly what's wrong
I know this is bad code but I find this kind of code interesting since the language supports linking so many if/else/for/lambda/whatever together into a single line.
You can rewrite the else case using reduce
(it’s functools.reduce
in Python 3):
if rot.isdigit():
s = s[-int(rot):] + s[:-int(rot)]
else:
s = rot.lower() + reduce(lambda x, y: x.replace(y, ''), rot.lower(), s)
And then you can combine it to one line:
s = s[-int(rot):] + s[:-int(rot)] if rot.isdigit() else rot.lower() + reduce(lambda x, y: x.replace(y, ''), rot.lower(), s)
But you’re absolutely right: It makes no sense to write it like this. It’s really unreadable.
Since you’re using Python 2, you can actually use str.translate
here too, to remove the characters in rot
from s
. This uses the deletechars
parameter of that function:
s = rot.lower() + s.translate(None, rot.lower())
Your one-line expression is then a little bit shorter:
s = s[-int(rot):] + s[:-int(rot)] if rot.isdigit() else rot.lower() + s.translate(None, rot.lower())