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.


 
 
 

2 Responses to “Morning coffee, 15 lines”

  1. José
    13. July 2009 at 19:27

    New May 2009 CTP does not have PowerPack.DLL as implicit reference. After an explicit reference I get this warning: warning FS0062: This construct is for compatibility with OCaml. Consider using System.Environment.GetCommandLineArgs directly. This warning can be disabled using ‘–mlcompatibility’, ‘–nowarn 62′ or ‘#nowarn “62″‘.

    I am not familiar with neither Sys.argv nor System.Environment.GetCommandLineArgs. What would be the required change in your program?

  2. djelovic
    6. August 2009 at 21:27

    José,

    Just replace Sys.argv (command-line arguments) with System.Environment.GetCommandLineArgs(). That should fix it.

    Dejan

Leave a Reply