Teil 2.
Zurück zum eigentlichen Problem. Hier übrigens Online RegEx to Finite State Machine Tool.
#load @"..\fingertree.fsx"
open FData.FingerTree
let inline flip f b a= f a b
//Finite State Machine for Regex ".*(.*007.*).*"
let inline fsm i c =
match i, c with
|0, '(' -> 1
|0, _ -> 0
|1, '0' -> 2
|1, _ -> 1
|2, '0' -> 3
|2, _ -> 1
|3, '7' -> 4
|3, '0' -> 3
|3, _ -> 1
|4, ')' -> 5
|4, _ -> 4
|5, _ -> 5
let inline tabulate f = Array.init 6 (fun i-> f i)
//Table with tabulated function for each letter in our alphabet.
let letters =
[|' '..'z'|]
|>Array.map (fun i->i,tabulate (flip fsm i))
|>Map.ofArray
type Table= int []
type Size =
|Size of int
//product monoid.
type Monoid() =
interface IMonoid<Size * Table> with
member inline this.Zero = Size 0,tabulate id
member inline this.Plus a b =
match a,b with
|(Size a, ta), (Size b, tb) -> Size (a + b), tabulate (fun st -> tb.[ta.[st]] )
type Element =
|Elem of char
interface IMeasured<Size * Table> with
member inline this.Value =
match this with
|Elem a ->
Size 1, Map.find a letters
type FingerString =FingerTree<Element,Size * Table, Monoid>
let inline matches007 (s:FingerString) = (snd (measured s)).[0]=5
let inline fromList s=(s,Empty)||> List.foldBack (push_front<<Elem)
let inline insert i c tree =
let (l,r) = split (fun (Size n,_) -> n>i) tree
concat l (push_front (Elem c) r)
let inline replace i c tree =
update (fun (Size n,_) -> n>i) (Elem c) tree
let treeString : seq<char>->FingerString = fromList<<List.ofSeq

//Simulate an interactive loop
let loop l f tree=
let res = List.fold (fun acc (i,c)->
let result= f i c acc
result) tree l
printfn "with Loop. Result %A" (matches007 res)
res

//Tests
open System
open System.Text.RegularExpressions
let test f =
printfn "Test Start"
let sw = new System.Diagnostics.Stopwatch()
sw.Start()
f()
sw.Stop()
printfn "Time Duration : %A" sw.ElapsedMilliseconds
//Regex for test.
let regex = new Regex (".*\(.*007.*\).*")
//String with 100 000 chars.
let str = String.Concat( Array.create 10000 " Match Me " )
//List of strings for test.
let listString=[str; str + "(007)"; "(007" + str + ")"; "(007)" + str]
//List of finger trees for test.
let listFingerString = List.map treeString listString
let runTest ()=
List.fold (fun acc str->
test (fun ()->printfn "with Regex %A. Result %A " acc (regex.Match(str).Success))
acc+1) 0 listString|>ignore
List.fold (fun acc str->
test (fun ()->printfn "with Finger Tree %A. Result %A " acc (matches007 str))
acc+1) 0 listFingerString|>ignore
runTest ()
test (fun ()->loop [(3,'(');(4000,'u');(20005,'0');(20006,'0');(20007,'7');(20008,'r');(40009,')');(40010,' ');(11,'I')] insert stringTree|>ignore)
test (fun ()->loop [(3,'(');(4,'0');(5,'0');(6,'7');(8,')');(40010,' ');(11,'I')] insert stringTree|>ignore)
test (fun ()->loop [(40004,'(');(40005,'0');(40006,'0');(40007,'7');(40008,'r');(40009,')');(40010,' ');(11,'I')] insert stringTree|>ignore)
test (fun ()->loop [(3,'(');(4000,'u');(20005,'0');(20006,'0');(20007,'7');(20008,'r');(40009,')');(40010,' ');(11,'I')] replace stringTree|>ignore)

