0

I'm trying to create a Caesar cypher decoder that takes in a coded message, looks for the most common letter used, assumes this letter is "e" (since it is the most commonly used letter), and then shifts the letters the correct amount of places until the whole message is decoded.

The coder only works with strings large enough to get a good reading on all the letters used, and rides on the hope that the string is an average sentence where "e" is used the most, but I'm not sure how to do this...

I'm new to Python and the first thing I thought of was to make a list of counters for each letter then check the number of instances each letter has in the string, adding 1 to whichever counter the letter works with. I don't know how to put this into code though...

  • Don't try to put code into comments. Just edit your question to add the code into it. – abarnert Oct 10 '14 at 00:23
  • Meanwhile, have you learned about dictionaries yet? Or using standard library modules like `collections`? If so, that will make life a lot easier. – abarnert Oct 10 '14 at 00:24
  • 1
    Cute idea. This article on [letter frequencies in English](http://en.wikipedia.org/wiki/Letter_frequency#Relative_frequencies_of_letters_in_the_English_language) may be helpful. OTOH, ['etaoinshrdlu'](http://en.wikipedia.org/wiki/Etaoin_shrdlu) may be sufficient for your purposes. FWIW, I used to be pretty good at cracking Caesar cyphers by hand in my younger days, but I've never gotten around to writing a program to do it. But I'd be interested in seeing your code... – PM 2Ring Oct 10 '14 at 02:19
  • @PM2Ring: The fun part is trying to figure out the backtracking logic you intuitively use, so you can code it up. I can (well, could, when I was younger…) often tell the difference between `t` being the 1st or 3rd most common instead of 2nd vs. the vowels being out of order, but I'm not sure how I knew it. – abarnert Oct 10 '14 at 23:00
  • @abarnert True! But at least with a Caesar cipher the possibilities are rather limited. Unlike a [Vigenère cipher]( http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher)... – PM 2Ring Oct 11 '14 at 02:25

1 Answers1

0

Counter can do most of the hard work for you:

>>> letters = 'imtryingtocreateacaesarcypherdecoder'
>>> c = collections.Counter(letters)

This gives you a mapping, where the letter 'e' is mapped to 6, 'r' to 5, 'c' and 'a' to 4, and so on. To find the most common letter, you just call the method most_common:

>>> c.most_common(1)
[('e', 6)]
>>> c.most_common(1)[0][0]
'e'

So, the only problem you have left is how to take your coded message, throw away all of the non-letters, and turn all of the letters into lowercase. If you look at the methods of the str type, you should be able to figure this out pretty easily.

(You might also want to use filter, or a comprehension; you may find that easier than something like str.translate. You don't actually need a string to pass to Counter, just any iterable of letters; a list or a generator expression is fine.)

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Thanks! I was able to get the majority of the code to work now thanks to you. The only problem I have now is whenever the letters "y" or "z" are in the sentence, they change to other characters that aren't part of the alphabet, but I'll put that in another question. Thank you everyone for the information! – Spook Chaser Oct 10 '14 at 02:50
  • 1
    @SpookChaser Don't forget to accept answers if you think they answered your question, it's the V mark on the left of the answer... – Maarten Bodewes Oct 10 '14 at 22:36
  • @SpookChaser : What do you mean `"y" or "z" [...] change to other characters that aren't part of the alphabet`? They shouldn't do that! I suspect there's a bug in your shifting routine. Post your code & we'll help you fix it, either here or in a new question. – PM 2Ring Oct 11 '14 at 02:28