This question already has an answer here:
How to write a Ceaser Cipher Python
(1 answer)
Closed 2 years ago.
I'm trying to write a function that is supposed to take a string like "abcd" and move the letter up or down by a certain number.
rolling_cipher("abcd", 1) ➞ "bcde"
Here is my code so far:
import string
def rolling_cipher(String, num):
letters = string.ascii_lowercase
print(letters)
String = String.index(string)
rolling_cipher("abcd", 2)
This is a possible solution:
from string import ascii_lowercase
def rolling_cipher(s, n):
idx = ascii_lowercase.index(s)
new_idx = (idx + n) % len(ascii_lowercase)
l = new_idx + len(s) - len(ascii_lowercase)
a1 = ascii_lowercase[new_idx: new_idx + len(s)]
a2 = '' if l <= 0 else ascii_lowercase[: l]
return a1 + a2
Examples:
>>> rolling_cipher('abcd', 3)
'defg'
>>> rolling_cipher('rst', 6)
'xyz'
>>> rolling_cipher('rst', 8)
'zab'
>>> rolling_cipher('rst', 33)
'yza'
You might alternatively want to use deque:
from collections import deque
from string import ascii_lowercase
def rolling_cipher(s, n):
d = deque(ascii_lowercase)
d.rotate(-ascii_lowercase.index(s) - n)
return ''.join(list(d)[:len(s)])
Just for fun, here's a one-liner that will do the trick:
import string
l = string.ascii_lowercase
s = 'eggs'
''.join(l[(l.rindex(i) + n) % 26] for i in s)
Output:
n = 1
>>> 'fhht'
n = 5
>>> 'jllx'
n = 100 # Same as -4
>>> 'acco'
n = -26
>>> 'eggs'
And, if you want to wrap it in a function:
def rolling(s, n) -> str:
"""Caesar cipher.
Args:
s (str): String to be encrypted.
n (int): Shift value.
Returns:
Encrypted string.
"""
return ''.join(l[(l.rindex(i) + n) % 26] for i in s)
Output:
rolling('eggs', -5)
>>> 'zbbn'
Try something like this
def foo(str:string, idx:int):
print(string.ascii_lowercase[idx: len(str) + idx])
Related
I want to create alphabetically ascending names like the column names in excel. That is I want to have smth. like a,b,c,...,z,aa,ab,...az,...zz,aaa,aab,....
I have tried:
for i in range(1000):
mod = int(i%26)
div = int(i/26)
print(string.ascii_lowercase[div]+string.ascii_lowercase[mod])
Which works until zz but than fails because it runs out of index
aa
ab
ac
ad
ae
af
ag
ah
ai
aj
ak
al
.
.
.
zz
IndexError
You could make use of itertools.product():
from itertools import product
from string import ascii_lowercase
for i in range(1, 4):
for x in product(ascii_lowercase, repeat=i):
print(''.join(x))
First, you want all letters, then all pairs, then all triplets, etc. This is why we first need to iterate through all the string lengths you want (for i in range(...)).
Then, we need all possible associations with the i letters, so we can use product(ascii_lowercase) which is equivalent to a nested for loop repeated i times.
This will generate the tuples of size i required, finally just join() them to obtain a string.
To continuously generate names without limit, replace the for loop with while:
def generate():
i = 0
while True:
i += 1
for x in product(ascii_lowercase, repeat=i):
yield ''.join(x)
generator = generate()
next(generator) # 'a'
next(generator) # 'b'
...
For a general solution we can use a generator and islice from itertools:
import string
from itertools import islice
def generate():
base = ['']
while True:
next_base = []
for b in base:
for i in range(26):
next_base.append(b + string.ascii_lowercase[i])
yield next_base[-1]
base = next_base
print('\n'.join(islice(generate(), 1000)))
And the output:
a
b
c
...
z
aa
ab
...
zz
aaa
aab
...
And you can use islice to take as many strings as you need.
Try:
>>import string
>>string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>len(string.ascii_lowercase)
26
When your index in below line exceed 26 it raise exception
div = int(i/26)
, becouse of ascii_lowercase length:
But you can:
for i in range(26*26): # <--- 26 is string.ascii_lowercase
mod = int(i%26)
div = int(i/26)
print(string.ascii_lowercase[div]+string.ascii_lowercase[mod])
EDIT:
or you can use:
import string
n = 4 # number of chars
small_limit = len(string.ascii_lowercase)
limit = small_limit ** n
i = 0
while i < limit:
s = ''
for c in range(n):
index = int(i/(small_limit**c))%small_limit
s += string.ascii_lowercase[index]
print(s)
i += 1
You can use:
from string import ascii_lowercase
l = list(ascii_lowercase) + [letter1+letter2 for letter1 in ascii_lowercase for letter2 in ascii_lowercase]+ [letter1+letter2+letter3 for letter1 in ascii_lowercase for letter2 in ascii_lowercase for letter3 in ascii_lowercase]
There's an answer to this question provided on Code Review SE
A slight modification to the answer in the link gives the following which works for an arbitrary number of iterations.
def increment_char(c):
return chr(ord(c) + 1) if c != 'z' else 'a'
def increment_str(s):
lpart = s.rstrip('z')
num_replacements = len(s) - len(lpart)
new_s = lpart[:-1] + increment_char(lpart[-1]) if lpart else 'a'
new_s += 'a' * num_replacements
return new_s
s = ''
for _ in range(1000):
s = increment_str(s)
print(s)
I would like to make a alphabetical list for an application similar to an excel worksheet.
A user would input number of cells and I would like to generate list.
For example a user needs 54 cells. Then I would generate
'a','b','c',...,'z','aa','ab','ac',...,'az', 'ba','bb'
I can generate the list from [ref]
from string import ascii_lowercase
L = list(ascii_lowercase)
How do i stitch it together?
A similar question for PHP has been asked here. Does some one have the python equivalent?
Use itertools.product.
from string import ascii_lowercase
import itertools
def iter_all_strings():
for size in itertools.count(1):
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
for s in iter_all_strings():
print(s)
if s == 'bb':
break
Result:
a
b
c
d
e
...
y
z
aa
ab
ac
...
ay
az
ba
bb
This has the added benefit of going well beyond two-letter combinations. If you need a million strings, it will happily give you three and four and five letter strings.
Bonus style tip: if you don't like having an explicit break inside the bottom loop, you can use islice to make the loop terminate on its own:
for s in itertools.islice(iter_all_strings(), 54):
print s
You can use a list comprehension.
from string import ascii_lowercase
L = list(ascii_lowercase) + [letter1+letter2 for letter1 in ascii_lowercase for letter2 in ascii_lowercase]
Following #Kevin 's answer :
from string import ascii_lowercase
import itertools
# define the generator itself
def iter_all_strings():
size = 1
while True:
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
size +=1
The code below enables one to generate strings, that can be used to generate unique labels for example.
# define the generator handler
gen = iter_all_strings()
def label_gen():
for s in gen:
return s
# call it whenever needed
print label_gen()
print label_gen()
print label_gen()
I've ended up doing my own.
I think it can create any number of letters.
def AA(n, s):
r = n % 26
r = r if r > 0 else 26
n = (n - r) / 26
s = chr(64 + r) + s
if n > 26:
s = AA(n, s)
elif n > 0:
s = chr(64 + n) + s
return s
n = quantity | r = remaining (26 letters A-Z) | s = string
To print the list :
def uprint(nc):
for x in range(1, nc + 1):
print AA(x,'').lower()
Used VBA before convert to python :
Function AA(n, s)
r = n Mod 26
r = IIf(r > 0, r, 26)
n = (n - r) / 26
s = Chr(64 + r) & s
If n > 26 Then
s = AA(n, s)
ElseIf n > 0 Then
s = Chr(64 + n) & s
End If
AA = s
End Function
Using neo's insight on a while loop.
For a given iterable with chars in ascending order. 'abcd...'.
n is the Nth position of the representation starting with 1 as the first position.
def char_label(n, chars):
indexes = []
while n:
residual = n % len(chars)
if residual == 0:
residual = len(chars)
indexes.append(residual)
n = (n - residual)
n = n // len(chars)
indexes.reverse()
label = ''
for i in indexes:
label += chars[i-1]
return label
Later you can print a list of the range n of the 'labels' you need using a for loop:
my_chrs = 'abc'
n = 15
for i in range(1, n+1):
print(char_label(i, my_chrs))
or build a list comprehension etc...
Print the set of xl cell range of lowercase and uppercase charterers
Upper_case:
from string import ascii_uppercase
import itertools
def iter_range_strings(start_colu):
for size in itertools.count(1):
for string in itertools.product(ascii_uppercase, repeat=size):
yield "".join(string)
input_colume_range = ['A', 'B']
input_row_range= [1,2]
for row in iter_range_strings(input_colume_range[0]):
for colum in range(int(input_row_range[0]), int(input_row_range[1]+1)):
print(str(row)+ str(colum))
if row == input_colume_range[1]:
break
Result:
A1
A2
B1
B2
In two lines (plus an import):
from string import ascii_uppercase as ABC
count = 100
ABC+=' '
[(ABC[x[0]] + ABC[x[1]]).strip() for i in range(count) if (x:= divmod(i-26, 26))]
Wrap it in a function/lambda if you need to reuse.
code:
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
for i in range(len(alphabet)):
for a in range(len(alphabet)):
print(alphabet[i] + alphabet[a])
result:
aa
ab
ac
ad
ae
af
ag
ah
ai
aj
ak
al
am
...
I would like to make a alphabetical list for an application similar to an excel worksheet.
A user would input number of cells and I would like to generate list.
For example a user needs 54 cells. Then I would generate
'a','b','c',...,'z','aa','ab','ac',...,'az', 'ba','bb'
I can generate the list from [ref]
from string import ascii_lowercase
L = list(ascii_lowercase)
How do i stitch it together?
A similar question for PHP has been asked here. Does some one have the python equivalent?
Use itertools.product.
from string import ascii_lowercase
import itertools
def iter_all_strings():
for size in itertools.count(1):
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
for s in iter_all_strings():
print(s)
if s == 'bb':
break
Result:
a
b
c
d
e
...
y
z
aa
ab
ac
...
ay
az
ba
bb
This has the added benefit of going well beyond two-letter combinations. If you need a million strings, it will happily give you three and four and five letter strings.
Bonus style tip: if you don't like having an explicit break inside the bottom loop, you can use islice to make the loop terminate on its own:
for s in itertools.islice(iter_all_strings(), 54):
print s
You can use a list comprehension.
from string import ascii_lowercase
L = list(ascii_lowercase) + [letter1+letter2 for letter1 in ascii_lowercase for letter2 in ascii_lowercase]
Following #Kevin 's answer :
from string import ascii_lowercase
import itertools
# define the generator itself
def iter_all_strings():
size = 1
while True:
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
size +=1
The code below enables one to generate strings, that can be used to generate unique labels for example.
# define the generator handler
gen = iter_all_strings()
def label_gen():
for s in gen:
return s
# call it whenever needed
print label_gen()
print label_gen()
print label_gen()
I've ended up doing my own.
I think it can create any number of letters.
def AA(n, s):
r = n % 26
r = r if r > 0 else 26
n = (n - r) / 26
s = chr(64 + r) + s
if n > 26:
s = AA(n, s)
elif n > 0:
s = chr(64 + n) + s
return s
n = quantity | r = remaining (26 letters A-Z) | s = string
To print the list :
def uprint(nc):
for x in range(1, nc + 1):
print AA(x,'').lower()
Used VBA before convert to python :
Function AA(n, s)
r = n Mod 26
r = IIf(r > 0, r, 26)
n = (n - r) / 26
s = Chr(64 + r) & s
If n > 26 Then
s = AA(n, s)
ElseIf n > 0 Then
s = Chr(64 + n) & s
End If
AA = s
End Function
Using neo's insight on a while loop.
For a given iterable with chars in ascending order. 'abcd...'.
n is the Nth position of the representation starting with 1 as the first position.
def char_label(n, chars):
indexes = []
while n:
residual = n % len(chars)
if residual == 0:
residual = len(chars)
indexes.append(residual)
n = (n - residual)
n = n // len(chars)
indexes.reverse()
label = ''
for i in indexes:
label += chars[i-1]
return label
Later you can print a list of the range n of the 'labels' you need using a for loop:
my_chrs = 'abc'
n = 15
for i in range(1, n+1):
print(char_label(i, my_chrs))
or build a list comprehension etc...
Print the set of xl cell range of lowercase and uppercase charterers
Upper_case:
from string import ascii_uppercase
import itertools
def iter_range_strings(start_colu):
for size in itertools.count(1):
for string in itertools.product(ascii_uppercase, repeat=size):
yield "".join(string)
input_colume_range = ['A', 'B']
input_row_range= [1,2]
for row in iter_range_strings(input_colume_range[0]):
for colum in range(int(input_row_range[0]), int(input_row_range[1]+1)):
print(str(row)+ str(colum))
if row == input_colume_range[1]:
break
Result:
A1
A2
B1
B2
In two lines (plus an import):
from string import ascii_uppercase as ABC
count = 100
ABC+=' '
[(ABC[x[0]] + ABC[x[1]]).strip() for i in range(count) if (x:= divmod(i-26, 26))]
Wrap it in a function/lambda if you need to reuse.
code:
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
for i in range(len(alphabet)):
for a in range(len(alphabet)):
print(alphabet[i] + alphabet[a])
result:
aa
ab
ac
ad
ae
af
ag
ah
ai
aj
ak
al
am
...
I was wondering if it is possible to convert numbers into their corresponding alphabetical value. So
1 -> a
2 -> b
I was planning to make a program which lists all the alphabetical combinations possible for a length specified by a user.
See I know how to build the rest of the program except this!
Any help would be wonderful.
Big Letter:
chr(ord('#')+number)
1 -> A
2 -> B
...
Small Letter:
chr(ord('`')+number)
1 -> a
2 -> b
...
import string
for x, y in zip(range(1, 27), string.ascii_lowercase):
print(x, y)
or
import string
for x, y in enumerate(string.ascii_lowercase, 1):
print(x, y)
or
for x, y in ((x + 1, chr(ord('a') + x)) for x in range(26)):
print(x, y)
All of the solutions above output lowercase letters from English alphabet along with their position:
1 a
...
26 z
You'd create a dictionary to access letters (values) by their position (keys) easily. For example:
import string
d = dict(enumerate(string.ascii_lowercase, 1))
print(d[3]) # c
You can use chr() to turn numbers into characters, but you need to use a higher starting point as there are several other characters in the ASCII table first.
Use ord('a') - 1 as a starting point:
start = ord('a') - 1
a = chr(start + 1)
Demo:
>>> start = ord('a') - 1
>>> a = chr(start + 1)
>>> a
'a'
Another alternative is to use the string.ascii_lowercase constant as a sequence, but you need to start indexing from zero:
import string
a = string.ascii_lowercase[0]
What about a dictionary?
>>> import string
>>> num2alpha = dict(zip(range(1, 27), string.ascii_lowercase))
>>> num2alpha[2]
b
>>> num2alpha[25]
y
But don't go over 26:
>>> num2alpha[27]
KeyError: 27
But if you are looking for all alphabetical combinations of a given length:
>>> import string
>>> from itertools import combinations_with_replacement as cwr
>>> alphabet = string.ascii_lowercase
>>> length = 2
>>> ["".join(comb) for comb in cwr(alphabet, length)]
['aa', 'ab', ..., 'zz']
Try a dict and some recursion:
def Getletterfromindex(self, num):
#produces a string from numbers so
#1->a
#2->b
#26->z
#27->aa
#28->ab
#52->az
#53->ba
#54->bb
num2alphadict = dict(zip(range(1, 27), string.ascii_lowercase))
outval = ""
numloops = (num-1) //26
if numloops > 0:
outval = outval + self.Getletterfromindex(numloops)
remainder = num % 26
if remainder > 0:
outval = outval + num2alphadict[remainder]
else:
outval = outval + "z"
return outval
Here is a quick solution:
# assumes Python 2.7
OFFSET = ord("a") - 1
def letter(num):
return chr(num + OFFSET)
def letters_sum_to(total):
for i in xrange(1, min(total, 27)):
for rem in letters_sum_to(total - i):
yield [letter(i)] + rem
if total <= 26:
yield [letter(total)]
def main():
for letters in letters_sum_to(8):
print("".join(letters))
if __name__=="__main__":
main()
which produces
aaaaaaaa
aaaaaab
aaaaaba
aaaaac
aaaabaa
aaaabb
aaaaca
aaaad
aaabaaa
# etc
Note that the number of solutions totalling to N is 2**(N-1).
for i in range(0, 100):
mul = 1
n = i
if n >= 26:
n = n-26
mul = 2
print chr(65+n)*mul
what's a simple way to increase the length of a string to an arbitrary integer x? like 'a' goes to 'z' and then goes to 'aa' to 'zz' to 'aaa', etc.
That should do the trick:
def iterate_strings(n):
if n <= 0:
yield ''
return
for c in string.ascii_lowercase:
for s in iterate_strings(n - 1):
yield c + s
It returns a generator.
You can iterate it with a for loop:
for s in iterate_strings(5)
Or get a list of the strings:
list(iterate_strings(5))
If you want to iterate over shorter strings too, you can use this function:
def iterate_strings(n):
yield ''
if n <= 0:
return
for c in string.ascii_lowercase:
for s in iterate_strings(n - 1):
yield c + s
Here's my solution, similar to Adam's, except it's not recursive. :].
from itertools import product
from string import lowercase
def letter_generator(limit):
for length in range(1, limit+1):
for letters in product(lowercase, repeat=length):
yield ''.join(letters)
And it returns a generator, so you can use a for loop to iterate over it:
for letters in letter_generator(5):
# ...
Have fun!
(This is the second time today I found itertools.product() useful. Woot.)
You can multiply the string in the integer.
For example
>>> 'a' * 2
'aa'
>>> 'a' * 4
'aaaa'
>>> 'z' * 3
'zzz'
>>> 'az' * 3
'azazaz'
Define x. I am using x = 5 for this example.
x = 5
import string
for n in range(1,x+1):
for letter in string.ascii_lowercase:
print letter*n