0

This here is an attempt to a Hill Cipher, so far so good until multiplication of the 2nd and 3rd trigram. I really don't understand where my mistake is. Basicly what I have to do is a list multiplication.

with this code I create a list of list

key=[k[x:x+3] for x in xrange(0, len(k), 3)]
message=[m[x:x+1] for x in xrange(0, len(m), 1)]    
key=[[16, 4, 11], [8, 6, 18], [15, 19, 15]]
message=[[0], [12], [8], [6], [15], [2], [15], [13], [3], [21], [2], [20], [15], [18], [8]]

My goal is to multiply every sublist or column in the key list by the first three lists in the message list

UPDATE: I have made a nested loop as suggested and also I have divided the message list into chunks but still I can't make it work.

Nested loop

result = [[0,],
         [0,],
         [0],]
#Divide the matrizm into chunks
n = 3
chunks = (matrizm[x:x+n] for x in range(0,len(matrizm), n))

#Matrix multiplication 
for triagram in chunks:
  # iterate through rows of X
  for i in range(len(matrizk)):
    # iterate through columns of Y
    for j in range(len(triagram[1])):
        # iterate through rows of Y
        for k in range(len(matrizk)):
           result[i][j] += matrizk[i][k] * triagram[k][j]

With my current code I just can multiply the first 3 triagrams that by the way gives me a incorrect result.

My question is, having this two list how could I multiply the first 3 triagrams and then another 3 and so on until the end of matrizk list

matrizk = [[16, 4, 11], [8, 6, 18], [15, 19, 15]]
matrizk = [[0], [12], [8], [6], [15], [2], [15], [13], [3], [21], [2], [20], [15], [18], [3]]
Cœur
  • 37,241
  • 25
  • 195
  • 267
etsous
  • 27
  • 6
  • What is the question? – wwii May 20 '15 at 02:08
  • Oops, Sorry I didn't made my self clear, How could I get `result=[[136], [216], [348], [178], [174], [405], [325], [252], [517], [564], [540], [653], [598], [696], [957]]` insted of just `result=[[136], [216], [348]]` – etsous May 20 '15 at 02:30
  • Basically, you found some code on the web that you don't know how it works and it almost does what you want and you want us to figure it out for you. – wwii May 20 '15 at 02:48
  • No way men, if anything I would like just some guidance to understand that piece of code since list comprehension is a bit dificult to me, no pun intended – etsous May 20 '15 at 03:02
  • Try to expand it out into nested for loops; update your question with the attempt, then ask any specific questions you have about your attempt. – wwii May 20 '15 at 04:06
  • Hey would you mind taking a look at my updated code? Thanks – etsous May 20 '15 at 20:29
  • How do ```matrizm``` and ```matrizk``` relate to ```message``` and ```key```? – wwii May 20 '15 at 21:18

1 Answers1

0

Answer assumes Python 2.7x

Data:

key=[[16, 4, 11], [8, 6, 18], [15, 19, 15]]
message=[[0], [12], [8], [6], [15], [2], [15], [13], [3], [21], [2], [20], [15], [18], [8]]

One thing that seems to complicate things is that message is a list of lists, to make things easier it will need to be flattened at some point.

I'll use an itertools recipe to get chunks of the message because I'm going to use a generator to flatten the message. There are other ways to flatten a list found in the answers to: How do you split a list into evenly sized chunks in Python?

import itertools
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 itertools.izip_longest(fillvalue=fillvalue, *args)
# flatten the message [[1],[2]] -> [1,2]
message = (item for thing in message for item in thing)

zip is another useful function, it is similar to a transposition:

>>> zip([1,2],[3,4])
[(1, 3), (2, 4)]
>>> 

Now we'll do a matrix multiplication with the key and each, 3 item, chunk of the message.

for group in grouper(message, n):
    # matrix multiplication
    for row in key:
        sum_prod = 0
        for a, b in zip(group, row):
            sum_prod += a*b
        #print(group, row, sum_prod, sum_prod % 26)
        result.append(sum_prod)
        #result.append(sum_prod % 26)
Community
  • 1
  • 1
wwii
  • 23,232
  • 7
  • 37
  • 77