let zstriv xs = let left_prod = Seq.scan ( * ) 1 xs let right_prod = Array.scanBack ( * ) xs 1 |> Seq.skip 1 Seq.map2 ( * ) left_prod right_prod let zssqrt (xs : int[]) = let block_len = xs.Length |> float |> sqrt |> int let block_prods = let array = Array.create ((xs.Length-1)/block_len+1) 1 Array.iteri (fun i x -> array.[i/block_len] <- array.[i/block_len] * x) xs zstriv array |> List.ofSeq let block = Array.zeroCreate block_len let rec zsblock (acc :: accs) = function | i when i >= xs.Length -> Seq.empty | i -> seq { for j = 0 to block_len - 1 do block.[j] <- if i+j < xs.Length then xs.[i+j] else 1 yield! (Seq.map (( *) acc) (zstriv block)) yield! zsblock accs (i + block_len) } zsblock block_prods 0 |> Seq.take xs.Length let zslog (xs : int[]) : seq = let rec prod acc i = function | j when j < i -> acc | j -> prod (acc * xs.[i]) (i+1) j let rec zs acc i : int -> seq = function | j when j < i -> Seq.empty | j when j = i -> Seq.singleton acc | j -> let m = (i + j) / 2 seq { yield! zs (acc * prod 1 (m+1) j) i m yield! zs (acc * prod 1 i m) (m+1) j } zs 1 0 (xs.Length-1) let main = printfn "%A" <| zstriv [|1; 2; 3; 4|] printfn "%A" <| zslog [|1; 2; 3; 4|] printfn "%A" <| zssqrt [|1; 2; 3; 4|]