I've been struggling in creating the vigenere table in python
That should be the result:
So basically I have the entire alphabet on the first line, and the alphabet shifted by one letter on the second one etc.
That's my code so far:
class CypherTable:
def __init__(self):
self.matrix = [[chr(i) for i in range(ord('a'),ord('z')+1)] for i in range(5)]
def __str__(self):
for i in range(len(self.matrix)):
print self.matrix[i]
return ""
table = CypherTable()
print(table)
I managed to print letters from a to z a number of times but I don't know how to modify each interaction in order to shift the first letter by one.
I'm used to work in java where you first define the array length and then populate it, but since python has a faster syntax I can't figure out what's the best way to do it.
A simpler way is to use the string module:
from string import ascii_uppercase as l
class CypherTable:
def __init__(self):
self.final_table = [l[i:]+l[:i] for i in range(len(l))]
for i in CypherTable().final_table:
print(i)
Output:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
BCDEFGHIJKLMNOPQRSTUVWXYZA
CDEFGHIJKLMNOPQRSTUVWXYZAB
DEFGHIJKLMNOPQRSTUVWXYZABC
EFGHIJKLMNOPQRSTUVWXYZABCD
FGHIJKLMNOPQRSTUVWXYZABCDE
GHIJKLMNOPQRSTUVWXYZABCDEF
HIJKLMNOPQRSTUVWXYZABCDEFG
IJKLMNOPQRSTUVWXYZABCDEFGH
JKLMNOPQRSTUVWXYZABCDEFGHI
KLMNOPQRSTUVWXYZABCDEFGHIJ
LMNOPQRSTUVWXYZABCDEFGHIJK
MNOPQRSTUVWXYZABCDEFGHIJKL
NOPQRSTUVWXYZABCDEFGHIJKLM
OPQRSTUVWXYZABCDEFGHIJKLMN
PQRSTUVWXYZABCDEFGHIJKLMNO
QRSTUVWXYZABCDEFGHIJKLMNOP
RSTUVWXYZABCDEFGHIJKLMNOPQ
STUVWXYZABCDEFGHIJKLMNOPQR
TUVWXYZABCDEFGHIJKLMNOPQRS
UVWXYZABCDEFGHIJKLMNOPQRST
VWXYZABCDEFGHIJKLMNOPQRSTU
WXYZABCDEFGHIJKLMNOPQRSTUV
XYZABCDEFGHIJKLMNOPQRSTUVW
YZABCDEFGHIJKLMNOPQRSTUVWX
ZABCDEFGHIJKLMNOPQRSTUVWXY
To be even cleaner, particularly if you will not be declaring any other methods in the class, you can use #classmethod:
from string import ascii_uppercase as l
class CypherTable:
final_table = [l[i:]+l[:i] for i in range(len(l))]
#classmethod
def show_board(cls):
for i in cls.final_table:
print(i)
CypherTable.show_board()
Regarding your recent comment, you can try this:
from string import ascii_uppercase as l
class CypherTable:
def __init__(self):
self.final_table = [l[i:]+l[:i] for i in range(len(l))]
def cross(self, b, a):
val1 = self.final_table[0].index(a)
new_letter = [i for i in self.final_table if i[0] == b][0][val1]
return new_letter
c = CypherTable()
print(c.cross('P', 'C'))
Output:
'R'
Here's your code with a minimum amount of changes. You can use modulo to loop from 26 back to 0. Note that __str__ should return a string and shouldn't print anything:
class CypherTable:
def __init__(self):
self.matrix = [[chr(ord('A') + (i + j) % 26) for i in range(26)] for j in range(5)]
def __str__(self):
return "\n".join('|'.join(row) for row in self.matrix)
table = CypherTable()
print(table)
It outputs:
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
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|A
C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B
D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C
E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D
Related
For a small language I want to parse expressions of the form "X [Y,Z,V]" where X, Y, Z, V are natural numbers.
Below is my attempt.
from pyparsing import *
class Y():
def __init__(self, ls):
self.ls = ls
def MakeCombinedList(tokens):
print(len(tokens)) # prints 4
print(tokens) # [5, 1, 2, 3]
clist = tokens[1]
clist.append(tokens[0]) # 'int' attribute object has no attribute 'append'
return clist
def MakeIntList(tokens):
nlist = tokens[0].split(",")
ilist = []
for n in nlist:
ilist.append(int(n))
return ilist
def MakeY(tokens):
Yobj = Y(tokens[0])
return Yobj
LEFT_BRACK = Suppress(Literal("["))
RIGHT_BRACK = Suppress(Literal("]"))
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine = True)
NATURAL_VEC = LEFT_BRACK + NATURAL_LIST + RIGHT_BRACK
NATURAL_VEC.addParseAction(MakeIntList)
X = NATURAL + NATURAL_VEC
X.addParseAction(MakeCombinedList)
Y = X
Y.addParseAction(MakeY)
print(Y.parseString("5 [1,2,3]").ls)
MakeIntList is supposed to transform a string such as "1,2,3" into the list [1,2,3].
MakeCombinedList is then supposed to append an integer to this list, but the tokens received by MakeCombinedList are not the single integer and the integer list created from MakeIntList, but a list of all the integers, as indicated by my comment.
How can I make tokens[1] inside MakeCombinedList be the result of calling MakeIntList?
These two lines are working against each other, since you use the first to parse separate numeric strings into ints, and then the second just combines them back into a comma-separated string.
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine=True)
The feature you are looking for is Group:
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = Group(delimitedList(NATURAL))
NATURAL_VEC = LEFT_BRACK + NATURAL_LIST + RIGHT_BRACK
# no MakeIntList parse action required
Now instead of creating a new string and then re-parsing it in a parse action, you use Group to tell pyparsing to make a sub-structure of the resulting tokens.
There is also a little confusion going on here:
Y = X
Y.addParseAction(MakeY)
This will redefine Y from the class defined at the top to a pyparsing expression, and you get some weird traceback when trying to accessing its ls attribute.
Y_expr = X
Y_expr.addParseAction(MakeY)
I wrote the runTests method to make it easier to do simple expression testing and printing, without having to deal with Py2/Py3 print differences:
Y_expr.runTests("""\
5 [1,2,3]
""")
Shows:
5 [1,2,3]
[<__main__.Y object at 0x00000241C57B7630>]
Since your Y class just uses the default __repr__ behavior, you can see the contents better if you define your own:
class Y():
def __init__(self, ls):
self.ls = ls
def __repr__(self):
return "{}: {}".format(type(self).__name__, vars(self))
Now runTests shows:
5 [1,2,3]
[Y: {'ls': 5}]
If the purpose of the Y class is to just give you attribute names for your parsed fields, consider using results names instead:
X = NATURAL('ls') + NATURAL_VEC
Y_expr = X
#~ Y_expr.addParseAction(MakeY)
# what you had written originally
print(Y_expr.parseString("5 [1,2,3]").ls)
Will just print:
5
i wrote code when input for example is "a" he return "h". But how i can make it work if i want to return array of characters, for example if is input "aa"
to return "hh"?
def input(s):
for i in range(len(s)):
ci = (ord(s[i])-90)%26+97
s = "".join(chr(ci))
return s
Never use built-in names as input
l = []
def input_x(s):
for i in s:
i = (ord(i)-90)%26+97
l.append(chr(i))
s = ''.join(l)
return s
You can use strings to do this. My variable finaloutput is a string that I will use to store all the updated characters.
def foo(s):
finaloutput = ''
for i in s:
finaloutput += chr((ord(i)-90)%26+97)
return finaloutput
This code uses string concatenation to add together a series of characters. Since strings are iterables, you can use the for loop shown above instead of the complex one that you used.
def input_x(s):
result = ""
for i in s:
ci = (ord(i)-90)%26+ 97
result += chr(ci)
print(result)
for some reason I am running into an issue where my function call seems to be overwriting the data read in from the file without me asking it to. I am trying to get the sum of the original list but I keep getting the sum of the squared list.
CODE:
def toNumbers(strList):
for i in range(len(strList)):
strList[i] = strList [int(i)]
return strList
def squareEach(nums):
for i in range(len(nums)):
nums[i] = eval(nums[i])
nums[i] = nums[i]**2
return nums
def sumList(nums):
b = sum(nums)
return b
def main():
file=open("numbers.txt","r").readline().split(" ")
print(str(squareEach(file)))
print(str(sumList(file)))
Your squareEach function modifies the original list which is passed to it.
To see what's going, consider adding a print between your function calls.
def main():
file=open("numbers.txt","r").readline().split(" ")
print(str(squareEach(file)))
print(str(file))
print(str(sumList(file))
EDIT:
The simplest fix would be to use a different list for storing your square numbers inside squareEach function
def squareEach(nums):
squares = []
for i in range(len(nums)):
num = eval(nums[i])
squares[i] = num**2
return squares
There are more efficient ways as suggested in other answers, but in your case, this appears to be the simplest fix.
The list nums is modified in squareEach method. Consider storing the results in a different list variable of the below sort:
def squareEach(nums):
sq = list()
for i in range(len(nums)):
sq.append(str(int(nums[i])**2))
# nums[i] = str(int(nums[i])**2)
return sq
I am not sure whether i am helping . But whatever you are trying to do can be done as follows
file=open("numbers.txt","r").readline().split(" ")
print ([int (m)**2 for m in file])
print (sum([int(m) for m in file]))
And if you want functions
def squareEach(file):
print ([int (m)**2 for m in file])
def sumList(file):
print (sum([int(m) for m in file]))
file=open("numbers.txt","r").readline().split(" ")
squareEach(file)
sumList(file)
I'm trying to write a function that joins a list of elements and then returns that join without the last character.
This is what I have so far:
n = ["Andy", "Warhol"]
def littery(word):
total = ''
for i in range(len(word)):
total = total + word[i]
return total
littery(n)
a = littery(n)[0:len(littery(n))-1]
print
The program prints: AndyWarho
Is there a better way to do this? I want to do this inside the function, without using: a = littery(n)[0:len(littery(n))-1]
If I understand what you're trying to do correctly, you can just do this:
def littery(lst):
return ''.join(lst)[:-1]
>>> littery(['Andy', 'Warhol'])
'AndyWarho'
Or if you want to take the last element off of each element of lst, you could do this:
def littery(lst):
return ''.join(word[:-1] for word in lst)
>>> littery(['Andy', 'Warhol'])
'AndWarho'
Or if you don't want to build a list in the call, you can do this:
def littery(*lst):
return ''.join(lst)[:-1]
>>> littery('Andy', 'Warhol')
'AndyWarho'
Or if you want to do it another way, you can do this:
def littery(*lst):
return ''.join(lst[:-1] + [lst[-1][:-1]])
Or if you might need the slice again at some point:
last = slice(-1)
def littery(*lst):
return ''.join(lst)[last]
Using Python I want to randomly rearrange sections of a string based on a given key. I also want to restore the original string with the same key:
def rearrange(key, data):
pass
def restore(key, rearranged_data):
pass
Efficiency is not important. Any ideas?
Edit:
can assume key is hashable, but may be multiple types
definition of section for ignacio
Use random.shuffle with the key as a seed:
import random
def rearrange(key, data):
random.seed(key)
d = list(data)
random.shuffle(d)
return ''.join(d)
def restore(key, rearranged_data):
l = len(rearranged_data)
random.seed(key)
d = range(l)
random.shuffle(d)
s = [None] * l
for i in range(l):
s[d[i]] = rearranged_data[i]
return ''.join(s)
x = rearrange(42, 'Hello, world!')
print x
print restore(42, x)
Output:
oelwrd!, llHo
Hello, world!
you can reinvent the wheel, but why not try an encryption library first, if possible.
An implementation that reverses the shuffling with sort():
import random
def reorder_list(ls, key):
random.seed(key)
random.shuffle(ls)
def reorder(s, key):
data = list(s)
reorder_list(data, key)
return ''.join(data)
def restore(s, key):
indexes = range(len(s))
reorder_list(indexes, key)
restored = sorted(zip(indexes, list(s)))
return ''.join(c for _, c in restored)