-2

In preparation for an upcoming national cipher challenge, I was hoping to create a piece of code that would take the coded message as a string and record the frequency of each letter in order to try and figure out what the letter is most likely to be when decoded (I'm sorry if that's not very clear!). This is how I planned to do this:


1) Copy + paste the code into a python program

2) The program would convert the letters to numbers

3) for x in range(0,len(name of variable the string is assigned to): if string[x] in "1":

increase count for '1' by one

x = x + 1

else:

x = x + 1

Then change it to

if string[x] in "2"

and so on until 26 when the program would print the frequency of each number. Any help whatsoever with this code would be appreciated. Even just some pseudocode would massively help.

Thank you!

Matt.

(PS, I'm completely new to this site!)

Mattymoo
  • 1
  • 3

2 Answers2

2

You can try Counter for counting frequency:

from collections import Counter
s = 'abahvhavsvgs'
print(Counter(s))

Output:

Counter({'v': 3, 'a': 3, 'h': 2, 's': 2, 'b': 1, 'g': 1})

For iterating over Counter (i.e. accessing particular element) you can use most_common() like:

c =Counter(s)
print(c.most_common())

Output: (list of tuples)

[('v', 3), ('a', 3), ('s', 2), ('h', 2), ('g', 1), ('b', 1)]

Note: If you want to see occurrence of particular letter let's say 'a', you can directly access it like print(c['a']) it gives output as 3 and if letter is not present in the string like 'z' if you execute print(c['z']) it gives output as 0

See also the documentation of Counter.most_common().So you can iterate over like if you do print(c.most_common()[0]) it will give output ('v', 3) as character with number of times it is occurred in the string.

For details about collections and counter see this Counter Explained.

Another Solution(using defaultdict ):

from collections import defaultdict
s = 'abahvhavsvgs'
d_int = defaultdict(int)    #  to make default value to 0 
for i in s:
    d_int[i] +=1
print(d_int)

Output:

defaultdict(<class 'int'>, {'v': 3, 'h': 2, 's': 2, 'b': 1, 'g': 1, 'a': 3})

You can convert it into dictionary by print(dict(d_int)) gives you output as {'g': 1, 's': 2, 'v': 3, 'h': 2, 'a': 3, 'b': 1} . Instead of using normal dictionary where every time you have to check if key is present in the dictionary (like in case of @Patrick Haugh solution) you can use defaultdict. For details about defaultdict you can this article defaultdict Document. (Note: But then you have to do additional logic to sort by value or to find which letter occurs most times or least times!).

Hope this helps.

Kalpesh Dusane
  • 1,477
  • 3
  • 20
  • 27
  • Ok, so could you talk me through how that works please? – Mattymoo Sep 15 '16 at 18:28
  • It will Count the number of occurrences in `list` or `string` or any other collections(it is pythonic way to do) for clear understanding read this http://stackoverflow.com/questions/2600191/how-can-i-count-the-occurrences-of-a-list-item-in-python/23909767#23909767 – Kalpesh Dusane Sep 15 '16 at 18:35
  • Ok, that helps a lot, thank you very much, will try this out :) – Mattymoo Sep 15 '16 at 19:07
1

Your post leads me to believe that you're an absolute beginner, so I think that it would be valuable for you to implement this on your own, so that you understand what's going on.

First: reading the cipher.

Instead of editing your code every time, you can read the contents of a file. Copy the cipher into a new txt file. I'll name mine "cipher.txt"

Then:

f = open('cipher.txt', 'r')

creates a file object named f that I can use to get the contents of a file. I will put all the text in the file onto one line, by removing the newline characters.

contents = r.read().replace('\n', '')

So contents is a string that holds all the text in our cipher. One of the nice things about strings in python is that they are iterable, so we can say

for char in contents:

to look at all the characters individually, in order.

But hold up! Where are we going to store our results? Let's assume that there could be any kind of character in our file, even one we may not expect. The other solution returned a list of tuples, but I like to use dictionaries for this kind of thing.

So let's make a dictionary

char_dict = {}

and start counting!

for char in contents:
    if char not in char_dict:
        char_dict[char] = 1
    else:
        char_dict[char] += 1

Dictionaries are just pairs of things. So if a char is not in our dictionary, we pair it with one. If it is in our dictionary, we increase the number we pair it with by one.

Then we can do things with the dictionary. To access 'a' in the dictionary you would just say

char_dict['a']

The other posters answer may be easier to write, but I hope this helped you understand a little bit of what's happening "under the hood", so to speak.

Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96