Anagram generation with F# Async

66 views Asked by At

I am trying to think of a way of how to improve speed of my program and one of the parts is anagram generation. Would the async features help in this case or there is another technique of manipulating strings?

let anagramWords = [|"rolex";"viagra";"win";"free";"cash";"grand";"prize";
                     "nude";"porn";"casino";"lottery";"spins";"sex";"gold"; "buy"; "clearance";
                     "business"; "biz"; "money"; "opportunity"; "earn"; "extra"; "potential"; "sleep"; "discount";
                     "bargain"; "credit"; "affordable"; "loans"; "mortages"; "quote"; "dollars"; "invest"; "investment";
                     "bitcoin"; "silver"; "save"; "unsecured"; "pennies"; "million"; "billion";"bureaus";"stock";
                     "bankruptcy"; "eliminate"; "debt"; "billing"; "iphone"; "selling"; "obligation";"trial";
                     "vacation"; "winner";"membership"; "preview"; "sample"; "priority"; "website"; "gift"; "gifts";
                     "present"; "deal"; "fantastic"; "outstanding"; "values"; "act"; "lifetime"; "urgent"|]



let rec distribute e = function
  | [] -> [[e]]
  | x::xs' as xs -> (e::xs)::[for xs in distribute e xs' -> x::xs]

let rec permute = function
  | [] -> [[]]
  | e::xs -> List.collect (distribute e) (permute xs)

let genAnagrams word = 
  word
  |>List.ofSeq 
  |>permute
  |> List.map (fun x -> String(x |> Array.ofList))
  |> Seq.ofList 
  |> Seq.toList
1

There are 1 answers

1
TheQuickBrownFox On

One very simple way to make this a bit faster is to make permute use arrays instead of lists and use Array.Parallel.collect instead of List.collect. Even with the inefficiency of taking the head off an array, it becomes about 30% faster for me for a word of 10 characters.

open System

let rec distribute e = function
  | [] -> [[e]]
  | x::xs' as xs -> (e::xs)::[for xs in distribute e xs' -> x::xs]

let arrayHeadTail = function [||] -> None | xs -> Some (xs.[0], Array.tail xs)

let rec permute xs =
    match arrayHeadTail xs with
    | None -> [| [] |]
    | Some (e, xs) -> Array.Parallel.collect (distribute e >> List.toArray) (permute xs)

let genAnagrams word = 
  word
  |> Seq.toArray
  |> permute
  |> Array.map String.Concat<char>