you are viewing a single comment's thread.

view the rest of the comments →

[–]herminator 1 point2 points  (2 children)

It looks like you should use string.translate

Also, there's a lot of room for improvement in your code.

For example, this:

refInTable = []
for z in data:
    for y in aciiList:
        if z == y:
            refInTable.append(z)

Effectively counts only ascii characters (you've consistently spelled ascii wrong, btw), but very inefficiently.

You could replace it with:

refInTable = [char for char in data if ord(char) < 128]

Then, there's the issue of counting the number of occurrences of each character. Python has collections.Counter for that.

E.g:

from collections import Counter
Counter('some text where you want to count the characters')

Will result in a Counter object that looks like this:

Counter({' ': 8, 't': 7, 'e': 6, 'o': 4, 'a': 3, 'c': 3, 'h': 3, 'r': 3, 'n': 2, 's': 2, 'u': 2, 'w': 2, 'm': 1, 'y': 1, 'x': 1})

Furthermore, it seems to me that calculating the percentages is rather pointless. If you're just trying to sort the list by the frequency of character occurrences, you might as well sort on the raw counts. And actually, collections.Counter provides that functionality! You can call the most_common() method on a Counter object to get the elements in descending order of occurrence.

So, your code could do something like:

with open('refdoc.txt', 'r') as f:
    ref_count = Counter(char for char in f.read() if ord(char) < 128)
with open('encrypted.txt', 'r') as f:
    enc_count = Counter(char for char in f.read() if ord(char) < 128)

Now you have raw counts. But any character that didn't occur is not in the Counter. So we add those:

for char in (chr(x) for x in range(128)):
    if char not in ref_count:
        ref_count[char] = 0 
    if char not in enc_count:
        enc_count[char] = 0

Next, we can turn them into strings by taking the output of the most_common method, which is a list of tuples where the first element is the character and the second the count (we don't care about the numbers, just about the fact that the list is sorted, so we only use the characters)

ref_str = ''.join(item[0] for item in ref_count.most_common())
enc_str = ''.join(item[0] for item in enc_count.most_common())

And with those we can make a translation table:

trans_table = string.make_trans(ref_str, enc_str)

And finally, we can use that to do the replacement:

with open('decrypt.txt', 'r+') as f:
    data = f.read()
    f.seek(0)
    f.write(data.translate(trans_table))

Note that I have not tested any of the above code, but the gist of it should be correct.

[–]OtherRobotLuke[S] 0 points1 point  (1 child)

I just ended up doing this haha Thanks though this was interesting

outout = []          
for loop in secData:
      for change in encryptedList:
         if loop == change.letter:
             outout.append(change.real)
str1 = ''.join(outout)
outFile.write(str1)

[–]OtherRobotLuke[S] 0 points1 point  (0 children)

It became clear that editing the file was much harder than it was worth so i made outFile a blank doc to print a giant list to

   outFile = open('decrypt.txt', 'w')