Sunday, December 24, 2006

ROT13 in F#

So, this is nothing really exciting, I wrote a simple program to do ROT13 text encoding, and in the way bumped into some minor quirks of the standard library. One of the problems with OCaml is its idiosyncratic standard library which is missing a lot of simple and useful functions. Granted, most of them you can write in less than five minutes, but it would be better if they were already done and standardized. I guess I became spoiled by Haskell. Anyway, F# seems to have inherited this as well. Below you can see the code, and a sample use case.

#light

let letters = Array.of_list(['a' .. 'z'] @ ['a' .. 'z'])

let index a c =
let rec aux i = if a.(i) = c then i else aux (i + 1) in
aux 0

let strmap f (s : string) =
let sb = new System.Text.StringBuilder(s) in
let rec aux i =
if i = sb.Length then () else
(sb.Chars(i) <- f (sb.Chars(i)) ; aux (i + 1)) in
( aux 0; sb.ToString() )

let rotchar c =
let i = index letters c in
letters.(i + 13)

let rot13 s =
strmap rotchar s

And now for the use case:

> rot13 "feijoada";;
val it : string = "srvwbnqn"

2 comments:

Anonymous said...

I don't have F#, but ocaml is close enough...

let rot13 str =
let s = String.copy str in
for i = 0 to String.length s - 1 do
if s.[i] >= 'a' && s.[i] <= 'z' then
s.[i] <- char_of_int ((int_of_char s.[i] - 84) mod 26 + 97)
done;
s

Martin Freedman said...

rot13Case case c = (int c - case + 13) % 26 + case |> char
let rot13Char c =
if System.Char.IsLetter c then
if System.Char.IsLower c then rot13Case (int 'a') c
else rot13Case (int 'A') c
else c
let rot13 = String.map rot13Char