LeetCode 1071. Greatest Common Divisor of Strings in F#

URL

Greatest Common Divisor of Strings - LeetCode

Code

https://github.com/syohex/dotnet-study/tree/master/fsharp/leetcode/problems/1071/main.fsx

open System

let commonDivisors (n1: int) (n2: int) : int list =
    let rec commonDivisors' i limit n1 n2 acc =
        if i > limit then
            List.rev acc
        else if n1 % i = 0 && n2 % i = 0 then
            commonDivisors' (i + 1) limit n1 n2 (i :: acc)
        else
            commonDivisors' (i + 1) limit n1 n2 acc

    commonDivisors' 1 (Math.Min(n1, n2)) n1 n2 []

let gcdOfStrings (str1: string) (str2: string) : string =
    let rec gcdOfStrings' divisors (cs1: char list) (cs2: char list) =
        match divisors with
        | [] -> ""
        | h :: t ->
            let c1 = List.take h cs1
            let c2 = List.take h cs2

            if c1 <> c2 then
                gcdOfStrings' t cs1 cs2
            else
                let ok1 = cs1 |> List.chunkBySize h |> List.forall (fun n -> c1 = n)
                let ok2 = cs2 |> List.chunkBySize h |> List.forall (fun n -> c2 = n)

                if ok1 && ok2 then
                    c1 |> String.Concat
                else
                    gcdOfStrings' t cs1 cs2

    let divisors = commonDivisors str1.Length str2.Length
    let cs1, cs2 = Seq.toList str1, Seq.toList str2

    gcdOfStrings' (divisors |> List.rev) cs1 cs2