1
\$\begingroup\$

Learn You a Haskell presents the Caesar Cipher:

The Caesar cipher is a primitive method of encoding messages by shifting each character in them by a fixed number of positions in the alphabet

EDIT

Since I'm not limiting this cipher to letters, it's not actually the Caesarian Cipher. Thanks to Anonymous. This implementation is only a Substitution Cipher.

Here's my implementation:

import Data.Char (ord, chr)

encode :: Int -> String -> String
encode n = map $ shift' n
                 where shift' x =  chr . (+ x) . ord

decode :: Int -> String -> String
decode n = map $ shift' n
                 where shift' x =  chr . abs . ((-) x) . ord

Test:

*Main Data.Char> encode 1 "AAA"
"BBB"
*Main Data.Char>
*Main Data.Char> decode 1 "BBB"
"AAA"

I don't like that I'm using abs in my decode. How can I write a function (through currying) that will subtract X from it?

Also, please critique my implementation.

\$\endgroup\$
  • \$\begingroup\$ Hey 200_Success, thanks for editing to include the proper tag. But, since Anonymous pointed out that it's only a Substitution Cipher, I edited the title and removed the tag. \$\endgroup\$ – Kevin Meredith May 18 '14 at 2:03
  • 1
    \$\begingroup\$ I suggest fixing the cipher to actually be Caesarean rather than just documenting the bug. It's a good exercise. Hint: isAsciiUpper, isAsciiLower and mod. \$\endgroup\$ – Anonymous May 18 '14 at 2:12
  • 1
    \$\begingroup\$ I've put the tag back, since it's still Caesar-inspired in nature. As the tag description says, caesar-cipher also applies to similar toy-grade ciphers. \$\endgroup\$ – 200_success May 18 '14 at 2:31
2
\$\begingroup\$

This is a legitimate substitution cipher, but it's not a Caesarean cipher. A Caesarian cipher affects only letters, and it's modulo the alphabet size: caesar 13 "Hello, world!""Urzzb, jbeyq!"

encode and decode can be the same function (caesar?) called with opposite shifts. (Or with the same shift, when it's 13.)

There's no need for a shift' helper.

How can I write a function (through currying) that will subtract X from it?

(x -)

\$\endgroup\$
  • \$\begingroup\$ thanks for mentioning that I'm not using the actual Caesarian Cipher. When you say that shift' is not needed, you recommend just putting the composed function directly in the map? \$\endgroup\$ – Kevin Meredith May 18 '14 at 2:00
  • \$\begingroup\$ Sorry, I didn't notice the map. shift is OK — yes, you could just write map (chr . (+ n) . ord) (as LYaH suggests). It's not necessary to pass n to shift, because it's in scope. \$\endgroup\$ – Anonymous May 18 '14 at 2:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.