Welcome to MSDN Blogs Sign in | Join | Help

F# Zen - ROT13

Below is a primitive implementation of ROT13 / Ceasar Cipher in F#. In short it is a simple encryption algorithm that works by 'shifting' each letter 13 places. So an 'a' becomes an 'n', a 'b' becomes an 'o', and so on. To decrypt the text you simply move 13 places in reverse.

We can do this in F# easily using function composition. Given a string, which is also a sequence of characters, we pass it to Array.of_seq so we have an array of characters. This will enable us to replace each character with its encrypted version. Next we map each character to our encryption function, which I'll go over next. Finally, we take our array of encrypted characters and return a new string.

To actually do the encryption, we will compose three functions together. int, will convert the character to its integer representation. "(+) 13" is a curried version of the (+) function, so it adds 13 to its argument. And then we compose that with the char function, which will convert the integer result to a character.

#light

(**
 * ROT13 in F#
 * 
 * 1. Convert the sequence of chars (string) to an array of chars
 * 2. For each character do the following:
 *    - Convert the character to an integer
 *    - Add 13 to the integer value of the character (by currying (+))
 *    - Convert the integer to a character
 * 3. Create a new string based off the encrypted characters
 *)
 
let EncryptText (text : string) = 
    text
    |> Array.of_seq
    |> Array.map (int >> ((+) 13) >> char)
    |> (fun chars -> new string(chars))

let DecryptText (text : string) = 
    text
    |> Array.of_seq
    |> Array.map (int >> ((+) -13) >> char)
    |> (fun chars -> new string(chars))

let Test message =
    let encrypted = EncryptText message
    let decrypted = DecryptText encrypted

    printfn "Original Message  = %s" message
    printfn "Encrypted Message = %s" encrypted
    printfn "Decrypted Message = %s" decrypted
    
Test "The quick fox jumped over the lazy dog"
Published Friday, November 07, 2008 2:33 PM by ChrSmith
Filed under: ,

Comments

Friday, November 07, 2008 5:40 PM by F# Zen - ROT13 | Tmao Coders

# F# Zen - ROT13 | Tmao Coders

Saturday, November 08, 2008 4:23 AM by Sergi Mansilla

# re: F# Zen - ROT13

I like how F# makes the algorithm be so simple and elegant, and I didn't know about this super simple way of casting chars into ints, thanks!

I recently made a F# implementation of Bruce Schneier's Solitaire encryption algorithm, you might want to check it out: http://www.sergimansilla.com/blog/?p=24

Your opinion will be really appreciated :)

Thanks for your articles!

Saturday, November 08, 2008 3:53 PM by Robert McCall

# re: F# Zen - ROT13

I feel uneasy about nitpicking like this, but it is even simpler via module [b]Microsoft.FSharp.Core.String[/b]'s [b]map[/b] function:

[code]let encryptText (s:string) =

 s |> String.map (int >> ((+) 13) >> char)

let decryptText (s:string) =

 s |> String.map (int >> ((+) -13) >> char)

[/code]

And thanks for the first practical (and beautifully elegant) use I've seen so far of fct composition -- I'm sure there are more to be discovered.

And, officially, everything about F# is tremendous from the lang design to the docs to shipping the source code.  You guys have set the new standard for combining high-level cs theory, real-world programmer productivity and exe performance.  After 20 years of professional programming (mostly C/C++/C# and various db systems), you guys have me excited about programming again.

-Robert

[i]"Lasting Peace and Happiness for [u][b]ALL[/b][/u] human beings."[/i]

Monday, November 10, 2008 12:35 AM by Carsten K.

# re: F# Zen - ROT13

well I guess I give my 25cents too:

You will see a lot of ROT13 "encrypted" messages in the usenet (to "hide" a solution, mark a spoiler etc.). In order to make your code really work there you will have to take care of some cases:

1) normaly only [a-z], [A-Z] gets encrypted so a->n, A->N but !->! for example.

2) You don't need a decrypt-function in those cases ;) - it's the same as the encryption function

Monday, November 10, 2008 9:03 AM by Patrick Dewane

# re: F# Zen - ROT13

At 13 characters, you're already halfway through the alphabet. Meaning you could have just 1 function for encrypting and decrypting.

Monday, November 10, 2008 12:14 PM by ChrSmith

# re: F# Zen - ROT13

@Patrick,

True, but if and only if you modulo the integer value of each character with 26. Since I'm blindly adding 13, 'z' becomes something outside the typical ASCII plane...

That's exactly why I didn't clame this 'was' an exact implementation of ROT13, but equivocated with 'primitive implementation of ROT13 / Ceasar Cipher'.

But yes, you are right. If you did the extra work you would only need one function for encrypting and decrypting.

Tuesday, November 11, 2008 8:39 AM by Patrick Dewane

# re: F# Zen - ROT13

How does one "read" the line:

  Array.map (int >> ((+) 13) >> char)

I like to apply a natural language to something I'm trying to learn, but I'm not sure of the correct way to say what this is doing.

Tuesday, November 11, 2008 12:55 PM by ChrSmith

# re: F# Zen - ROT13

That is the beauty of function composition :)

I'll probabaly need to devote an entire post to concept later, but in short:

Array.map takes a function which converts the array element to some new value. So in the context of ROT13 transforms a char to a new char.

[int >> (+) 13 >> char] is actually three functions glued together using the function composition operator (>>).

[int] takes an input and converts it to an integer, so 'A' is converted to 65.

[(+) 13] is the (+) function with the first parameter specified as 13, so it is a function that takes an input of an integer and returns 13 plus that integer.

[char] takes an input and converts it to a character. So 65' is converted to 'A'.

By composing those three functions [int >> (+) 13 >> char] the result is a new function that takes anything, converts it to an integer, adds 13, and converts that to a character.

So when applied via Array.map it encrypts the input string.

Function composition is one of the core conepts of functional programming, but definitely requires a bit of time to wrap your head around.

Tuesday, November 11, 2008 1:29 PM by Patrick Dewane

# re: F# Zen - ROT13

Thanks for the explanation. It doesn't look like function composition from what I know of the subject. Knowing that ">>" is the function composition operator makes it really easy to read the line now, thanks again.

Friday, November 14, 2008 3:31 AM by Jay Hugard

# re: F# Zen - ROT13

This doesn't show clever use of function composition (very cool, by the way), but it does provide a traditional rot13 implementation:

let rot13 =

   let rot b c = (int c - int b + 13) % 26 + int b |> char

   String.map (function

                | 'A'..'Z' as c -> rot 'A' c

                | 'a'..'z' as c -> rot 'a' c

                | c -> c )

Wednesday, May 06, 2009 9:31 AM by Frederico Pessoa

# re: F# Zen - ROT13

Summing all cents:

let rot13 s =

   let rotc = function

       | i when 97 <= i && i <= 122 -> (i - 84) % 26 + 97

       | i when 65 <= i && i <= 90 -> (i - 52) % 26 + 65

       | i -> i

   s |> String.map (int >> rotc >> char)

Wednesday, May 06, 2009 9:35 AM by Frederico Pessoa

# re: F# Zen - ROT13

And I do miss python 0 <= x <= 100 construct...

New Comments to this post are disabled
 
Page view tracker