0

I am trying to create a collision counter in python that will count every time there is the same character in the same spot in two lists. I'm doing this to try and determine the key length used in a Vigenère cipher text.

For example, I have a cipher text c = "aabaab", which I've converted to a list. I shift the characters 1 spot so c_shift = "baabaa" and now I count the number of "collisions", aka the same characters in the same spots. In this example there are 2 collisions, one at position 1, and another at position 4.

In my real code, I have a much larger cipher text and want to shift the cipher text 26 times, and get a collision count for each shift. My shift code works, however the counting collisions part does not. In the end, I want it to print out the shift (1 - 26) and the total number of collisions for that shift.

I've tried multiple stack overflow tutorials with little success. I tried to use zip, but it threw an error when I typed [collisions += 1 for k, l in zip(c, c_shift) if k == l]. I've also tried set(c).intersection(c_shift) but I couldn't figure out how to tie that in with the counter.

c = list(c) #converts cipher text to list
# creates list variable c_shift equal to cipher text c
c_shift = c
for j in range(1, 26): # I want to shift cipher text 26 times
    collisions = 0
    # remove last character from ciphertext
    last: str = c_shift.pop()

    # add last character to front of ciphertext (shifting by 1 every 
    # time for loop iterates)
    c_shift.insert(0, last)

    #this is where my code stops functioning correctly. 

    for k, l in zip(c, c_shift):
        if k == l:
            collisions += 1
    print(j, " ", collisions)

I want an output that shows both the shift and the number of total collisions.

For example: [1 , 7], [2, 36], [3, 97], [4, 10]...

where first numbers 1,2,3,4,... is the shift 1-26, and the next number is the the max number of collisions for each shift.

martineau
  • 119,623
  • 25
  • 170
  • 301
Vic
  • 33
  • 1
  • 9
  • I want c to stay the same and c_shift to shift 1 - 26 times. I realized from Anon Coward's answer that I was accidentally making c and c_shift dependent on eachother, so c_shift was changing c. – Vic Sep 08 '19 at 16:49
  • I don't believe you want nested for loops here. You're comparing `c[0]` to _each_ character in `c_shift`, then `c[1]` to _each_ character in `c_shift`, etc. I don't think you want to do that. – John Gordon Sep 08 '19 at 16:50
  • You're right. I ended up having to change the nested for loops to: for k, l in zip(t, t_shift): if k == l: collisions += 1 to get it to work. I just updated my initial post to reflect this change! Sorry for the confusion! – Vic Sep 08 '19 at 17:00
  • Possible duplicate of [How to clone or copy a list?](https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list) – Carcigenicate Sep 09 '19 at 00:31

1 Answers1

1
c = list(c)
c_shift = c

This is the core of the issue. You're creating a list, then storing it in c, then storing a reference to that list in c_shift. Any changes to the reference of c_shift will also impact c.

You want to create two different lists:

c, c_shift = list(c), list(c)

This creates two list objects, and any changes you make to c_shift won't change c as well.

Anon Coward
  • 9,784
  • 3
  • 26
  • 37
  • Oh my god this fixed it! Thank you so much I've been struggling with this for days! – Vic Sep 08 '19 at 16:46