Reputation: 43
Currently working on a transposition problem. What I have so far is that a user enters a message and that message is encrypted into a list, like below:
['BC', 'DE', 'DE', 'DA', 'FD', 'DD', 'BE', 'FE', 'DA', 'EA', 'FE', 'BC']
What I have for the next stage of the cipher is putting this into a table with a key inputted from the user. So if the user enters 'CODE' it outputs this:
2: Enter the keyword for final encryption: code
C O D E
['B', 'C', 'D', 'E']
['D', 'E', 'D', 'A']
['F', 'D', 'D', 'D']
['B', 'E', 'F', 'E']
['D', 'A', 'E', 'A']
['F', 'E', 'B', 'C']
The next stage is to take each value of each column and print the values corresponding to its alphabetical column. So my expected output would be:
C D E O
['B', 'D', 'E', 'C']
['D', 'D', 'A', 'E']
['F', 'D', 'D', 'D']
['B', 'F', 'E', 'E']
['D', 'E', 'A', 'A']
['F', 'B', 'C', 'E']
The problem I'm having is trying to know how to put each of the values in their corresponding column and printing them.
Here's what I have so far:
def encodeFinalCipher():
matrix2 = []
# Convert keyword to upper case
key = list(keyword.upper())
# Convert firstEncryption to a string
firstEncryptionString = ''.join(str(x) for x in firstEncryption)
# Print the first table that will show the firstEncryption and the keyword above it
keywordList = list(firstEncryptionString)
for x in range(0,len(keywordList),len(keyword)):
matrix2.append(list(keywordList[x:x+len(keyword)]))
# Print the un-ordered matrix to the screen
print (' %s' % ' '.join(map(str, key)))
for letters in matrix2:
print (letters)
unOrderedMatrix = [[matrix2[i][j] for i in range(len(matrix2))] for j in range(len(matrix2[0]))]
for index, item in enumerate (unOrderedMatrix):
print("\n",index, item)
index = sorted(key)
print(index)
I get the output of the sorted key:
['A', 'K', 'M', 'R']
What I would like to know is how can this sorted key be applied to the values they represent? I know I can get the first column by doing this:
print(unOrderedMatrix[0])
Which gets me the list of the first column.
Any help would be much appreciated. Complete beginner on Python
Upvotes: 4
Views: 161
Reputation: 23753
msg = ['BC', 'DE', 'DE', 'DA', 'FD', 'DD', 'BE', 'FE', 'DA', 'EA', 'FE', 'BC', '12']
key = 'CODE'
# 'flatten' the message
msg = ''.join(msg)
key_length = len(key)
#create a dictionary with the letters of the key as the keys
#use a slice to create the values
columns = {k:msg[i::key_length] for i, k in enumerate(key)}
print columns
# sort the columns on the key letters
columns = sorted(columns.items())
print columns
# separate the key from the columnar data
header, data = zip(*columns)
print header
# transpose and print
for thing in zip(*data):
print thing
>>>
{'C': 'BDFBDF1', 'E': 'EADEAC', 'D': 'DDDFEB', 'O': 'CEDEAE2'}
[('C', 'BDFBDF1'), ('D', 'DDDFEB'), ('E', 'EADEAC'), ('O', 'CEDEAE2')]
('C', 'D', 'E', 'O')
('B', 'D', 'E', 'C')
('D', 'D', 'A', 'E')
('F', 'D', 'D', 'D')
('B', 'F', 'E', 'E')
('D', 'E', 'A', 'A')
('F', 'B', 'C', 'E')
>>>
Upvotes: 1
Reputation: 23364
With help from itertools
from pprint import pprint
from itertools import chain, izip_longest
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
z = ['BC', 'DE', 'DE', 'DA', 'FD', 'DD', 'BE', 'FE', 'DA', 'EA', 'FE', 'BC']
input = 'CODE'
pprint([[b for (a, b) in sorted(zip(input, x))]
for x in grouper(chain.from_iterable(z), len(input))])
[['B', 'D', 'E', 'C'],
['D', 'D', 'A', 'E'],
['F', 'D', 'D', 'D'],
['B', 'F', 'E', 'E'],
['D', 'E', 'A', 'A'],
['F', 'B', 'C', 'E']]
Upvotes: 0
Reputation: 31339
Here is something to get you started (you may want to separate the loop one-liner to smaller bits):
# define data
data = [['B', 'C', 'D', 'E'], ['D', 'E', 'D', 'A'], ['F', 'D', 'D', 'D'], ['B', 'E', 'F', 'E'], ['D', 'A', 'E', 'A'], ['F', 'E', 'B', 'C']]
# choose code word
code = 'code'
# add original locations to code word [(0, c), (1, o), (2, d), (3, e))]
# and sort them alphabetically!
code_with_locations = list(sorted(enumerate(code)))
print code_with_locations # [(0, 'c'), (2, 'd'), (3, 'e'), (1, 'o')]
# re-organize data according to new indexing
for index in range(len(data)):
# check if code is shorter than list in current index,
# or the other way around, don't exceed either list
max_substitutions = min(map(len, [code_with_locations, data[index]]))
# create a new list according to new indices
new_list = []
for i in range(max_substitutions):
current_index = code_with_locations[i][0]
new_list.append(data[index][current_index])
# replace old list with new list
data[index] = new_list
print data
Output for 'code' would be:
[['B', 'D', 'E', 'C'],
['D', 'D', 'A', 'E'],
['F', 'D', 'D', 'D'],
['B', 'F', 'E', 'E'],
['D', 'E', 'A', 'A'],
['F', 'B', 'C', 'E']]
Upvotes: 1
Reputation: 5275
code = raw_input("Enter the keyword for final encryption:")
user_input = ['BC', 'DE', 'DE', 'DA', 'FD', 'DD', 'BE', 'FE', 'DA', 'EA', 'FE', 'BC']
user_input = ''.join(user_input)
matrix = [user_input[i:i+len(code)] for i in range(0, len(user_input), len(code))]
matrix.insert(0, code)
result = sorted([[matrix[j][ind] for j in range(len(matrix))] for ind in range(len(code)) ], key= lambda i:i[0])
for row in [[each[ind] for each in result] for ind in range(len(result[0]))]:
print row
Print row
results as:
Enter the keyword for final encryption:CODE
['C', 'D', 'E', 'O']
['B', 'D', 'E', 'C']
['D', 'D', 'A', 'E']
['F', 'D', 'D', 'D']
['B', 'F', 'E', 'E']
['D', 'E', 'A', 'A']
['F', 'B', 'C', 'E']
Upvotes: 1