Morning coffee, 15 lines
This morning I decided to use the reduce function in lieu of the missing ?? operator I talked about yesterday. This shaved off another line:
#light
open System.Text.RegularExpressions
let (+..) = Seq.append
let edits1 (w:string) =
seq { for i in { 0 .. w.Length - 1} -> w.Remove(i, 1) } +..
seq { for i in { 0 .. w.Length - 2 } -> w.Remove(i + 1, 1).Insert(i, w.[i + 1].ToString()) } +..
seq { for i in { 0 .. w.Length - 1 } do for c in { 'a' .. 'z' } -> w.Remove(i, 1).Insert (i, c.ToString()) } +..
seq { for i in { 0 .. w.Length } do for c in { 'a' .. 'z' } -> w.Insert (i, c.ToString()) }
let re = Regex ("[a-zA-Z]+", RegexOptions.Compiled)
let words = System.IO.File.ReadAllText "big.txt" |> re.Matches |> Seq.cast |> Seq.map (fun (x:Match) -> x.Value.ToLower())
let wordMap = words |> Seq.count_by id |> Map.of_seq
for arg in Seq.skip 1 Sys.argv do
let cor = [arg |> Seq.singleton; edits1 arg; edits1 arg |> Seq.map_concat edits1]
|> Seq.map (Seq.filter wordMap.ContainsKey) |> Seq.reduce (fun x y -> if Seq.is_empty x then y else x)
printf "%s\n" (if Seq.is_empty cor then arg else cor |> Seq.max_by (fun w -> wordMap.[w]))
Changes from yesterday’s code:
1. Simplified the edits1 function using string Insert and Remove functions. This makes the lines shorter.
2. The cascading cor1 –> cor2 –> cor3 has been replaced by a call to reduce.
3. Replaced the call to Seq.sort_by followed by a call to Seq.hd by Seq.max_by. I’m a moron.
4. The program now attempts to correct all passed arguments, one by one. It bugged me that the code would break for no command-line arguments because it was accessing Sys.argv.[1].
Notes:
1. The edits1 function can definitely be shaved by one line. But limitations of either F# or my knowledge are preventing from doing it in an elegant manner. To be continued…
2. In addition to standard implicit conversions (int to float, etc.), all languages should have an implicit conversion from char to string. I know that the ML language family eschews implicit conversions because of type inference, but it still strikes me as wrong. C++ has shown that it’s possible to have both implicit conversions and type inference (which it does for generic function calls), and though it does one or the other and the Koeing lookup complicates the language definition, it’s still both useful and safe.

I know they are not very scientific. I know they don’t show real-world code. I know that the results depend on the skill of individual contributors. But whether shoot-outs compare speed or brevity I still love them, for a simple reason: They let me see a lot of languages in action at once. If you look at the results as an order of magnitude thing rather than as an exact comparison, they become telling.
Prompted by a blog post I watched