Powered by AppSignal & Oban Pro

Perf (Polyglot)

apps/perf/Perf.livemd

Perf (Polyglot)

#!import ../../lib/fsharp/Notebooks.dib

#!import ../../lib/fsharp/Testing.dib

Spiral.Cells.eval!(
  ~S"""

  open testing
  open benchmark
  """,
  timeout: 300_000
)
#if !INTERACTIVE
open Lib
#endif

TestCaseResult

type TestCaseResult =
    {
        Input: string
        Expected: string
        Result: string
        TimeList: int64 list
    }

run

let run count (solutions: (string * ('TInput -> 'TExpected)) list) (input, expected) =
    let inputStr =
        match box input with
        | :? System.Collections.ICollection as input ->
            System.Linq.Enumerable.Cast<obj> input
            |> Seq.map string
            |> SpiralSm.concat ","
        | _ -> input.ToString ()

    printfn ""
    printfn $"Solution: {inputStr}  "

    let performanceInvoke (fn: unit -> 'T) =
        GC.Collect ()
        let stopwatch = System.Diagnostics.Stopwatch ()
        stopwatch.Start ()
        let time1 = stopwatch.ElapsedMilliseconds

        let result =
            [| 0 .. count |]
            |> Array.Parallel.map (fun _ ->
                fn ()
            )
            |> Array.last

        let time2 = stopwatch.ElapsedMilliseconds - time1

        result, time2

    let resultsWithTime =
        solutions
        |> List.mapi (fun i (testName, solution) ->
            let result, time = performanceInvoke (fun () -> solution input)
            printfn $"Test case %d{i + 1}. %s{testName}. Time: %A{time}  "
            result, time
        )


    match resultsWithTime |> List.map fst with
    | ([] | [ _ ]) -> ()
    | (head :: tail) when tail |> List.forall ((=) head) -> ()
    | results -> failwithf $"Challenge error: %A{results}"

    {
        Input = inputStr
        Expected = expected.ToString ()
        Result = resultsWithTime |> Seq.map fst |> Seq.head |> _.ToString()
        TimeList = resultsWithTime |> List.map snd
    }

runAll

let runAll testName count (solutions: (string * ('TInput -> 'TExpected)) list) testCases =
    printfn ""
    printfn ""
    printfn $"Test: {testName}"
    testCases
    |> Seq.map (run count solutions)
    |> Seq.toList

sortResultList

let sortResultList resultList =
    let table =
        let rows =
            resultList
            |> List.map (fun result ->
                let best =
                    result.TimeList
                    |> List.mapi (fun i time ->
                        i + 1, time
                    )
                    |> List.sortBy snd
                    |> List.head
                    |> _.ToString()
                let row =
                    [
                        result.Input
                        result.Expected
                        result.Result
                        best
                    ]
                let color =
                    match result.Expected = result.Result with
                    | true -> Some ConsoleColor.DarkGreen
                    | false -> Some ConsoleColor.DarkRed
                row, color
            )
        let header =
            [
                [
                    "Input"
                    "Expected"
                    "Result"
                    "Best"
                ]
                [
                    "---"
                    "---"
                    "---"
                    "---"
                ]
            ]
            |> List.map (fun row -> row, None)
        header @ rows

    let formattedTable =
        let lengthMap =
            table
            |> List.map fst
            |> List.transpose
            |> List.map (fun column ->
                column
                |> List.map String.length
                |> List.sortDescending
                |> List.tryHead
                |> Option.defaultValue 0
            )
            |> List.indexed
            |> Map.ofList
        table
        |> List.map (fun (row, color) ->
            let newRow =
                row
                |> List.mapi (fun i cell ->
                    cell.PadRight lengthMap.[i]
                )
            newRow, color
        )

    printfn ""
    formattedTable
    |> List.iter (fun (row, color) ->
        match color with
        | Some color -> Console.ForegroundColor <- color
        | None -> Console.ResetColor ()

        printfn "%s" (String.Join ("\t| ", row))

        Console.ResetColor ()
    )

    let averages =
        resultList
        |> List.map (fun result -> result.TimeList |> List.map float)
        |> List.transpose
        |> List.map List.average
        |> List.map int64
        |> List.indexed

    printfn ""
    printfn "Average Ranking  "
    averages
    |> List.sortBy snd
    |> List.iter (fun (i, avg) ->
        printfn $"Test case %d{i + 1}. Average Time: %A{avg}  "
    )
let mutable _count =
    if ("CI" |> System.Environment.GetEnvironmentVariable |> fun x -> $"%A{x}") <> "<null>"
    then 2000000
    else 2000
Spiral.Cells.eval!(
  ~S"""
  inl is_fast () =
      false
  """,
  timeout: 300_000
)

empty3Tests

Test: Empty3

Solution: (a, a) Test case 1. A. Time: 91L

Solution: (a, a) Test case 1. A. Time: 56L

Input Expected Result Best
(a, a) a a (1, 91)
(a, a) a a (1, 56)

Averages Test case 1. Average Time: 73L

Ranking Test case 1. Average Time: 73L


let solutions = [
    "A",
    fun (a, _b) ->
        a
]
let testCases = seq {
    ("a", "a"), "a"
    ("a", "a"), "a"
}
let rec empty3Tests = runAll (nameof empty3Tests) _count solutions testCases
empty3Tests
|> sortResultList

empty2Tests

Test: Empty2

Solution: (a, a) Test case 1. A. Time: 59L

Solution: (a, a) Test case 1. A. Time: 53L

Input Expected Result Best
(a, a) a a (1, 59)
(a, a) a a (1, 53)

Averages Test case 1. Average Time: 56L

Ranking Test case 1. Average Time: 56L


let solutions = [
    "A",
    fun (a, _b) ->
        a
]
let testCases = seq {
    ("a", "a"), "a"
    ("a", "a"), "a"
}
let rec empty2Tests = runAll (nameof empty2Tests) _count solutions testCases
empty2Tests
|> sortResultList

emptyTests

Test: Empty

Solution: 0 Test case 1. A. Time: 61L

Solution: 2 Test case 1. A. Time: 62L

Solution: 5 Test case 1. A. Time: 70L

Input Expected Result Best
0 0 0 (1, 61)
2 2 2 (1, 62)
5 5 5 (1, 70)

Averages Test case 1. Average Time: 64L

Ranking Test case 1. Average Time: 64L


let solutions = [
    "A",
    fun n ->
        n + 0
]
let testCases = seq {
    0, 0
    2, 2
    5, 5
}
let rec emptyTests = runAll (nameof emptyTests) _count solutions testCases
emptyTests
|> sortResultList

uniqueLettersTests

Test: UniqueLetters

Solution: abc Test case 1. A. Time: 1512L Test case 2. B. Time: 1947L Test case 3. C. Time: 2023L Test case 4. D. Time: 1358L Test case 5. E. Time: 1321L Test case 6. F. Time: 1346L Test case 7. G. Time: 1304L Test case 8. H. Time: 1383L Test case 9. I. Time: 1495L Test case 10. J. Time: 1245L Test case 11. K. Time: 1219L

Solution: accabb Test case 1. A. Time: 1648L Test case 2. B. Time: 2061L Test case 3. C. Time: 2413L Test case 4. D. Time: 1561L Test case 5. E. Time: 1593L Test case 6. F. Time: 1518L Test case 7. G. Time: 1415L Test case 8. H. Time: 1510L Test case 9. I. Time: 1445L Test case 10. J. Time: 1636L Test case 11. K. Time: 1317L

Solution: pprrqqpp Test case 1. A. Time: 2255L Test case 2. B. Time: 2408L Test case 3. C. Time: 2393L Test case 4. D. Time: 1675L Test case 5. E. Time: 1911L Test case 6. F. Time: 2126L Test case 7. G. Time: 1504L Test case 8. H. Time: 1715L Test case 9. I. Time: 1537L Test case 10. J. Time: 1522L Test case 11. K. Time: 1322L

Solution: aaaaaaaaaaaaaaccccccabbbbbbbaaacccbbbaaccccccccccacbbbbbbbbbbbbbcccccccbbbbbbbb Test case 1. A. Time: 13073L Test case 2. B. Time: 11519L Test case 3. C. Time: 8373L Test case 4. D. Time: 5860L Test case 5. E. Time: 6490L Test case 6. F. Time: 6325L Test case 7. G. Time: 5799L Test case 8. H. Time: 7099L Test case 9. I. Time: 6133L Test case 10. J. Time: 5993L Test case 11. K. Time: 2040L

Input Expected Result Best
abc abc abc (11, 1219)
accabb acb acb (11, 1317)
pprrqqpp prq prq (11, 1322)
aaaaaaaaaaaaaaccccccabbbbbbbaaacccbbbaaccccccccccacbbbbbbbbbbbbbcccccccbbbbbbbb acb acb (11, 2040)

Averages Test case 1. Average Time: 4622L Test case 2. Average Time: 4483L Test case 3. Average Time: 3800L Test case 4. Average Time: 2613L Test case 5. Average Time: 2828L Test case 6. Average Time: 2828L Test case 7. Average Time: 2505L Test case 8. Average Time: 2926L Test case 9. Average Time: 2652L Test case 10. Average Time: 2599L Test case 11. Average Time: 1474L

Ranking Test case 1. Average Time: 4622L Test case 2. Average Time: 4483L Test case 3. Average Time: 3800L Test case 8. Average Time: 2926L Test case 5. Average Time: 2828L Test case 6. Average Time: 2828L Test case 9. Average Time: 2652L Test case 4. Average Time: 2613L Test case 10. Average Time: 2599L Test case 7. Average Time: 2505L Test case 11. Average Time: 1474L


let solutions = [
    "A",
    fun input ->
        input
        |> Seq.toList
        |> List.fold (fun acc x -> if List.contains x acc then acc else acc @ [ x ]) []
        |> Seq.toArray
        |> String

    "B",
    fun input ->
        input
        |> Seq.rev
        |> fun list -> Seq.foldBack (fun x acc -> if List.contains x acc then acc else x :: acc) list []
        |> Seq.rev
        |> Seq.toArray
        |> String

    "C",
    fun input ->
        input
        |> Seq.rev
        |> fun list -> Seq.foldBack (fun x (set, acc) -> if Set.contains x set then set, acc else set.Add x, x :: acc) list (Set.empty, [])
        |> snd
        |> Seq.rev
        |> Seq.toArray
        |> String

    "D",
    fun input ->
        input
        |> Seq.fold (fun (set, acc) x -> if Set.contains x set then set, acc else set.Add x, Array.append acc [| x |]) (Set.empty, [||])
        |> snd
        |> String

    "E",
    fun input ->
        input
        |> Seq.fold (fun (set, acc) x -> if Set.contains x set then set, acc else set.Add x, x :: acc) (Set.empty, [])
        |> snd
        |> List.rev
        |> List.toArray
        |> String

    "F",
    fun input ->
        input
        |> Seq.fold (fun (set, acc) x -> if Set.contains x set then set, acc else set.Add x, acc @ [ x ]) (Set.empty, [])
        |> snd
        |> List.toArray
        |> String

    "G",
    fun input ->
        input
        |> Seq.fold (fun (set, acc) x -> if Set.contains x set then set, acc else set.Add x, x :: acc) (Set.empty, [])
        |> snd
        |> List.toArray
        |> Array.rev
        |> String

    "H",
    fun input ->
        input
        |> Seq.toList
        |> fun list ->
            let rec 루프 set = function
                | head :: tail when Set.contains head set -> 루프 set tail
                | head :: tail -> (루프 (set.Add head) tail) @ [ head ]
                | [] -> []
            루프 Set.empty list
            |> List.rev
        |> List.toArray
        |> String

    "I",
    fun input ->
        input
        |> Seq.toList
        |> fun list ->
            let rec 루프 set = function
                | head :: tail when Set.contains head set -> 루프 set tail
                | head :: tail -> 루프 (set.Add head) tail |> Array.append [| head |]
                | [] -> [||]
            루프 Set.empty list
        |> String

    "J",
    fun input ->
        input
        |> Seq.toList
        |> fun list ->
            let rec 루프 set = function
                | head :: tail when Set.contains head set -> 루프 set tail
                | head :: tail -> head :: 루프 (set.Add head) tail
                | [] -> []
            루프 Set.empty list
        |> List.toArray
        |> String

    "K",
    fun input ->
        input
        |> Seq.distinct
        |> Seq.toArray
        |> String
]
let testCases = seq {
    "abc", "abc"
    "accabb", "acb"
    "pprrqqpp", "prq"
    "aaaaaaaaaaaaaaccccccabbbbbbbaaacccbbbaaccccccccccacbbbbbbbbbbbbbcccccccbbbbbbbb", "acb"
}
let rec uniqueLettersTests = runAll (nameof uniqueLettersTests) _count solutions testCases
uniqueLettersTests
|> sortResultList

rotateStringsTests

https://www.hackerrank.com/challenges/rotate-string/forum

Test: RotateStrings

Solution: abc Test case 1. A. Time: 1842L Test case 2. B. Time: 1846L Test case 3. C. Time: 1936L Test case 4. CA. Time: 2224L Test case 5. CB. Time: 2329L Test case 6. D. Time: 2474L Test case 7. E. Time: 1664L Test case 8. F. Time: 1517L Test case 9. FA. Time: 1651L Test case 10. FB. Time: 3764L Test case 11. FC. Time: 5415L

Solution: abcde Test case 1. A. Time: 3356L Test case 2. B. Time: 2592L Test case 3. C. Time: 2346L Test case 4. CA. Time: 2997L Test case 5. CB. Time: 3061L Test case 6. D. Time: 4051L Test case 7. E. Time: 1905L Test case 8. F. Time: 1771L Test case 9. FA. Time: 2175L Test case 10. FB. Time: 3275L Test case 11. FC. Time: 5266L

Solution: abcdefghi Test case 1. A. Time: 4492L Test case 2. B. Time: 3526L Test case 3. C. Time: 3583L Test case 4. CA. Time: 3711L Test case 5. CB. Time: 4783L Test case 6. D. Time: 7557L Test case 7. E. Time: 3452L Test case 8. F. Time: 3050L Test case 9. FA. Time: 3275L Test case 10. FB. Time: 4635L Test case 11. FC. Time: 5616L

Solution: abab Test case 1. A. Time: 2093L Test case 2. B. Time: 1843L Test case 3. C. Time: 1746L Test case 4. CA. Time: 2085L Test case 5. CB. Time: 2139L Test case 6. D. Time: 2095L Test case 7. E. Time: 1723L Test case 8. F. Time: 1558L Test case 9. FA. Time: 1620L Test case 10. FB. Time: 2319L Test case 11. FC. Time: 3918L

Solution: aa Test case 1. A. Time: 1107L Test case 2. B. Time: 1241L Test case 3. C. Time: 1183L Test case 4. CA. Time: 1563L Test case 5. CB. Time: 1525L Test case 6. D. Time: 1591L Test case 7. E. Time: 1327L Test case 8. F. Time: 1151L Test case 9. FA. Time: 1180L Test case 10. FB. Time: 1733L Test case 11. FC. Time: 2817L

Solution: z Test case 1. A. Time: 816L Test case 2. B. Time: 745L Test case 3. C. Time: 928L Test case 4. CA. Time: 1375L Test case 5. CB. Time: 1029L Test case 6. D. Time: 852L Test case 7. E. Time: 712L Test case 8. F. Time: 263L Test case 9. FA. Time: 232L Test case 10. FB. Time: 773L Test case 11. FC. Time: 1789L

Input Expected Result Best
abc bca cab abc bca cab abc (8, 1517)
abcde bcdea cdeab deabc eabcd abcde bcdea cdeab deabc eabcd abcde (8, 1771)
abcdefghi bcdefghia cdefghiab defghiabc efghiabcd fghiabcde ghiabcdef hiabcdefg iabcdefgh abcdefghi bcdefghia cdefghiab defghiabc efghiabcd fghiabcde ghiabcdef hiabcdefg iabcdefgh abcdefghi (8, 3050)
abab baba abab baba abab baba abab baba abab (8, 1558)
aa aa aa aa aa (1, 1107)
z z z (9, 232)

Averages Test case 1. Average Time: 2284L Test case 2. Average Time: 1965L Test case 3. Average Time: 1953L Test case 4. Average Time: 2325L Test case 5. Average Time: 2477L Test case 6. Average Time: 3103L Test case 7. Average Time: 1797L Test case 8. Average Time: 1551L Test case 9. Average Time: 1688L Test case 10. Average Time: 2749L Test case 11. Average Time: 4136L

Ranking Test case 11. Average Time: 4136L Test case 6. Average Time: 3103L Test case 10. Average Time: 2749L Test case 5. Average Time: 2477L Test case 4. Average Time: 2325L Test case 1. Average Time: 2284L Test case 2. Average Time: 1965L Test case 3. Average Time: 1953L Test case 7. Average Time: 1797L Test case 9. Average Time: 1688L Test case 8. Average Time: 1551L


let solutions = [
    "A",
    fun (input: string) ->
        let resultList =
            List.fold (fun acc x ->
                let rotate (text: string) (letter: string) = (text |> SpiralSm.slice 1 (input.Length - 1)) + letter
                [ rotate (if acc.IsEmpty then input else acc.Head) (string x) ] @ acc
            ) [] (Seq.toList input)

        (resultList, "")
        ||> List.foldBack (fun acc x -> x + acc + " ")
        |> _.TrimEnd()

    "B",
    fun input ->
        input
        |> Seq.toList
        |> List.fold (fun (acc: string list) letter ->
            let last =
                if acc.IsEmpty
                then input
                else acc.Head

            let item = last.[1 .. input.Length - 1] + string letter

            item :: acc
        ) []
        |> List.rev
        |> SpiralSm.concat " "

    "C",
    fun input ->
        input
        |> Seq.toList
        |> List.fold (fun (acc: string list) letter -> acc.Head.[ 1 .. input.Length - 1 ] + string letter :: acc) [ input ]
        |> List.rev
        |> List.skip 1
        |> SpiralSm.concat " "

    "CA",
    fun input ->
        input
        |> Seq.fold (fun (acc: string list) letter -> acc.Head.[ 1 .. input.Length - 1 ] + string letter :: acc) [ input ]
        |> Seq.rev
        |> Seq.skip 1
        |> SpiralSm.concat " "

    "CB",
    fun input ->
        input
        |> Seq.toArray
        |> Array.fold (fun (acc: string[]) letter -> acc |> Array.append [| acc.[0].[ 1 .. input.Length - 1 ] + string letter |]) [| input |]
        |> Array.rev
        |> Array.skip 1
        |> SpiralSm.concat " "

    "D",
    fun input ->
        input
        |> Seq.toList
        |> fun list ->
            let rec 루프 (acc: char list list) = function
                | _ when acc.Length = list.Length -> acc
                | head :: tail ->
                    let item = tail @ [ head ]
                    루프 (item :: acc) item
                | [] -> []
            루프 [] list
        |> List.rev
        |> List.map (List.toArray >> String)
        |> SpiralSm.concat " "

    "E",
    fun input ->
        input
        |> Seq.toList
        |> fun list ->
            let rec 루프 (last: string) = function
                | head :: tail ->
                    let item = last.[1 .. input.Length - 1] + string head
                    item :: 루프 item tail
                | [] -> []
            루프 input list
        |> SpiralSm.concat " "

    "F",
    fun input ->
        Array.singleton 0
        |> Array.append [| 1 .. input.Length - 1 |]
        |> Array.map (fun i -> input.[ i .. ] + input.[ .. i - 1 ])
        |> SpiralSm.concat " "

    "FA",
    fun input ->
        List.singleton 0
        |> List.append [ 1 .. input.Length - 1 ]
        |> List.map (fun i -> input.[ i .. ] + input.[ .. i - 1 ])
        |> SpiralSm.concat " "

    "FB",
    fun input ->
        Seq.singleton 0
        |> Seq.append (seq { 1 .. input.Length - 1 })
        |> Seq.map (fun i -> input.[ i .. ] + input.[ .. i - 1 ])
        |> SpiralSm.concat " "

    "FC",
    fun input ->
        Array.singleton 0
        |> Array.append [| 1 .. input.Length - 1 |]
        |> Array.Parallel.map (fun i -> input.[ i .. ] + input.[ .. i - 1 ])
        |> SpiralSm.concat " "
]
let testCases = seq {
    "abc", "bca cab abc"
    "abcde", "bcdea cdeab deabc eabcd abcde"
    "abcdefghi", "bcdefghia cdefghiab defghiabc efghiabcd fghiabcde ghiabcdef hiabcdefg iabcdefgh abcdefghi"
    "abab", "baba abab baba abab"
    "aa", "aa aa"
    "z", "z"
}
let rec rotateStringsTests = runAll (nameof rotateStringsTests) _count solutions testCases
rotateStringsTests
|> sortResultList

rotate_strings_tests

02:21:12 verbose #1 benchmark.run_all / {count = 2000000; test_name = rotate_strings_tests}

02:21:12 verbose #2 benchmark.run / {input_str = "abc"}
02:21:13 verbose #3 benchmark.run / solutions.map / {i = 1; test_name = F; time = 638}
02:21:14 verbose #4 benchmark.run / solutions.map / {i = 2; test_name = FA; time = 779}

02:21:14 verbose #5 benchmark.run / {input_str = "abcde"}
02:21:15 verbose #6 benchmark.run / solutions.map / {i = 1; test_name = F; time = 745}
02:21:16 verbose #7 benchmark.run / solutions.map / {i = 2; test_name = FA; time = 809}

02:21:16 verbose #8 benchmark.run / {input_str = "abcdefghi"}
02:21:17 verbose #9 benchmark.run / solutions.map / {i = 1; test_name = F; time = 1092}
02:21:18 verbose #10 benchmark.run / solutions.map / {i = 2; test_name = FA; time = 1304}

02:21:18 verbose #11 benchmark.run / {input_str = "abab"}
02:21:19 verbose #12 benchmark.run / solutions.map / {i = 1; test_name = F; time = 536}
02:21:20 verbose #13 benchmark.run / solutions.map / {i = 2; test_name = FA; time = 620}

02:21:20 verbose #14 benchmark.run / {input_str = "aa"}
02:21:21 verbose #15 benchmark.run / solutions.map / {i = 1; test_name = F; time = 365}
02:21:21 verbose #16 benchmark.run / solutions.map / {i = 2; test_name = FA; time = 396}

02:21:21 verbose #17 benchmark.run / {input_str = "z"}
02:21:22 verbose #18 benchmark.run / solutions.map / {i = 1; test_name = F; time = 158}
02:21:22 verbose #19 benchmark.run / solutions.map / {i = 2; test_name = FA; time = 143}
input expected result best
"abc" "bca cab abc" "bca cab abc" 1, 638
"abcde" "bcdea cdeab deabc eabcd abcde" "bcdea cdeab deabc eabcd abcde" 1, 745
"abcdefghi" "bcdefghia cdefghiab defghiabc efghiabcd fghiabcde ghiabcdef hiabcdefg iabcdefgh abcdefghi" "bcdefghia cdefghiab defghiabc efghiabcd fghiabcde ghiabcdef hiabcdefg iabcdefgh abcdefghi" 1, 1092
"abab" "baba abab baba abab" "baba abab baba abab" 1, 536
"aa" "aa aa" "aa aa" 1, 365
"z" "z" "z" 2, 143
02:21:22 verbose #20 benchmark.sort_result_list / averages.iter / {avg = 589; i = 1}
02:21:22 verbose #21 benchmark.sort_result_list / averages.iter / {avg = 675; i = 2}
Spiral.Cells.eval!(
  ~S"""

  inl get_solutions () =
      [










          "F",
          fun input =>
              inl input_length = input |> sm.length
              arraym.singleton 0i32
              |> arraym.append (am'.init_series 1 (input_length - 1) 1 |> fun x => array x : array _)
              |> fun (array x) => x
              |> am'.map_base fun i =>
                  inl a = input |> sm'.slice i (input_length - 1)
                  inl b = input |> sm'.slice 0 (i - 1)
                  sm'.(++#) a b
              |> fun x => array x : array _
              |> seq.of_array
              |> sm'.concat " "

          "FA",
          fun input =>
              inl input_length = input |> sm.length
              listm.singleton 0i32
              |> listm.append (listm'.init_series 1 (input_length - 1) 1)
              |> listm.map (fun i =>
                  inl a = input |> sm'.slice i (input_length - 1)
                  inl b = if i = 0 then "" else input |> sm'.slice 0 (i - 1)
                  sm'.(++#) a b
              )
              |> listm'.box
              |> listm'.to_array'
              |> fun x => array x : array _
              |> seq.of_array
              |> sm'.concat " "


      ]

  inl rec rotate_strings_tests () =
      inl test_cases = [
          "abc", "bca cab abc"
          "abcde", "bcdea cdeab deabc eabcd abcde"
          "abcdefghi", "bcdefghia cdefghiab defghiabc efghiabcd fghiabcde ghiabcdef hiabcdefg iabcdefgh abcdefghi"
          "abab", "baba abab baba abab"
          "aa", "aa aa"
          "z", "z"
      ]

      inl solutions = get_solutions ()


      inl count =
          if is_fast ()
          then 1000i32
          else 2000000i32

      run_all (reflection.nameof { rotate_strings_tests }) count solutions test_cases
      |> sort_result_list

  rotate_strings_tests ()
  """,
  timeout: 300_000
)
Spiral.Cells.eval!(
  ~S"""

  ()
  """,
  timeout: 300_000
)

binary_search_tests

02:19:29 verbose #1 benchmark.run_all / {count = 10000000; test_name = binary_search_tests}

02:19:29 verbose #2 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 6, 7)}
02:19:30 verbose #3 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 662}
02:19:30 verbose #4 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 619}
02:19:31 verbose #5 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 644}
02:19:32 verbose #6 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 610}

02:19:32 verbose #7 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 1, 7)}
02:19:33 verbose #8 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 607}
02:19:33 verbose #9 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 559}
02:19:34 verbose #10 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 612}
02:19:35 verbose #11 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 577}

02:19:35 verbose #12 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 11, 7)}
02:19:35 verbose #13 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 550}
02:19:36 verbose #14 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 580}
02:19:37 verbose #15 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 624}
02:19:37 verbose #16 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 590}

02:19:37 verbose #17 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 12, 7)}
02:19:38 verbose #18 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 574}
02:19:39 verbose #19 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 577}
02:19:39 verbose #20 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 582}
02:19:40 verbose #21 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 585}

02:19:40 verbose #22 benchmark.run / {input_str = struct ([|1; 2; 3; 4...00; ...|], 60, 1000)}
02:19:41 verbose #23 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 610}
02:19:42 verbose #24 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 672}
02:19:42 verbose #25 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 636}
02:19:43 verbose #26 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 629}

02:19:43 verbose #27 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 6, 7)}
02:19:44 verbose #28 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 599}
02:19:44 verbose #29 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 561}
02:19:45 verbose #30 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 604}
02:19:46 verbose #31 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 573}

02:19:46 verbose #32 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 1, 7)}
02:19:47 verbose #33 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 635}
02:19:47 verbose #34 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 603}
02:19:48 verbose #35 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 644}
02:19:49 verbose #36 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 628}

02:19:49 verbose #37 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 11, 7)}
02:19:49 verbose #38 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 643}
02:19:50 verbose #39 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 606}
02:19:51 verbose #40 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 636}
02:19:52 verbose #41 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 624}

02:19:52 verbose #42 benchmark.run / {input_str = struct ([|1; 3; 4; 6; 8; 9; 11|], 12, 7)}
02:19:52 verbose #43 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 689}
02:19:53 verbose #44 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 613}
02:19:54 verbose #45 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 623}
02:19:55 verbose #46 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 613}

02:19:55 verbose #47 benchmark.run / {input_str = struct ([|1; 2; 3; 4...100; ...|], 60, 100)}
02:19:55 verbose #48 benchmark.run / solutions.map / {i = 1; test_name = semi_open_1; time = 630}
02:19:56 verbose #49 benchmark.run / solutions.map / {i = 2; test_name = closed_1; time = 633}
02:19:57 verbose #50 benchmark.run / solutions.map / {i = 3; test_name = semi_open_2; time = 653}
02:19:58 verbose #51 benchmark.run / solutions.map / {i = 4; test_name = closed_2; time = 646}
input expected result best
struct ([1; 3; 4; 6; 8; 9; 11], 6, 7) US4_0 3 US4_0 3 4, 610
struct ([1; 3; 4; 6; 8; 9; 11], 1, 7) US4_0 0 US4_0 0 2, 559
struct ([1; 3; 4; 6; 8; 9; 11], 11, 7) US4_0 6 US4_0 6 1, 550
struct ([1; 3; 4; 6; 8; 9; 11], 12, 7) US4_1 US4_1 1, 574
struct ([1; 2; 3; 4...00; ...], 60, 1000) US4_0 59 US4_0 59 1, 610
struct ([1; 3; 4; 6; 8; 9; 11], 6, 7) US4_0 3 US4_0 3 2, 561
struct ([1; 3; 4; 6; 8; 9; 11], 1, 7) US4_0 0 US4_0 0 2, 603
struct ([1; 3; 4; 6; 8; 9; 11], 11, 7) US4_0 6 US4_0 6 2, 606
struct ([1; 3; 4; 6; 8; 9; 11], 12, 7) US4_1 US4_1 2, 613
struct ([1; 2; 3; 4...100; ...], 60, 100) US4_0 59 US4_0 59 1, 630
02:19:58 verbose #52 benchmark.sort_result_list / averages.iter / {avg = 602; i = 2}
02:19:58 verbose #53 benchmark.sort_result_list / averages.iter / {avg = 607; i = 4}
02:19:58 verbose #54 benchmark.sort_result_list / averages.iter / {avg = 619; i = 1}
02:19:58 verbose #55 benchmark.sort_result_list / averages.iter / {avg = 625; i = 3}
Spiral.Cells.eval!(
  ~S"""

  inl binary_search_semi_open_1 arr target left right =
      inl rec body left right =
          if left >= right
          then None
          else
              inl mid = (left + right) / 2
              inl item = index arr mid
              if item = target
              then Some mid
              elif item < target
              then 루프 (mid + 1) right
              else 루프 left mid
      and inl 루프 left right =
          if var_is right |> not
          then body left right
          else
              inl left = dyn left
              join body left right
      루프 left right

  inl binary_search_closed_1 arr target left right =
      inl rec body left right =
          if left > right
          then None
          else
              inl mid = (left + right) / 2
              inl item = index arr mid
              if item = target
              then Some mid
              elif item < target
              then 루프 (mid + 1) right
              else 루프 left (mid - 1)
      and inl 루프 left right =
          if var_is right |> not
          then body left right
          else
              inl left = dyn left
              join body left right
      루프 left right

  inl binary_search_semi_open_2 arr target left right =
      let rec body left right =
          if left >= right
          then None
          else
              inl mid = (left + right) / 2
              inl item = index arr mid
              if item = target
              then Some mid
              elif item < target
              then 루프 (mid + 1) right
              else 루프 left mid
      and inl 루프 left right = body left right
      루프 left right

  inl binary_search_closed_2 arr target left right =
      let rec body left right =
          if left > right
          then None
          else
              inl mid = (left + right) / 2
              inl item = index arr mid
              if item = target
              then Some mid
              elif item < target
              then 루프 (mid + 1) right
              else 루프 left (mid - 1)
      and inl 루프 left right = body left right
      루프 left right

  inl get_solutions () =
      [
          "semi_open_1",
          fun (arr, (target, len)) =>
              binary_search_semi_open_1 arr target 0 len

          "closed_1",
          fun (arr, (target, len)) =>
              binary_search_closed_1 arr target 0 (len - 1)

          "semi_open_2",
          fun (arr, (target, len)) =>
              binary_search_semi_open_2 arr target 0 len

          "closed_2",
          fun (arr, (target, len)) =>
              binary_search_closed_2 arr target 0 (len - 1)
      ]

  inl rec binary_search_tests () =
      inl arr_with_len target len arr =
          arr, (target, (len |> optionm'.default_with fun () => length arr))

      inl test_cases = [
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 6 None), (Some 3i32)
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 1 None), (Some 0i32)
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 11 None), (Some 6i32)
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 12 None), None
          ((am'.init_series 1i32 1000 1 |> fun x => array x : array _) |> arr_with_len 60 None), (Some 59)

          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 6 (Some 7)), (Some 3i32)
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 1 (Some 7)), (Some 0i32)
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 11 (Some 7)), (Some 6i32)
          (;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 12 (Some 7)), None
          ((am'.init_series 1i32 1000 1 |> fun x => array x : array _) |> arr_with_len 60 (Some 100)), (Some 59)
      ]

      inl solutions = get_solutions ()


      inl count =
          if is_fast ()
          then 1000i32
          else 10000000i32

      run_all (reflection.nameof { binary_search_tests }) count solutions test_cases
      |> sort_result_list


  let main () =
      binary_search_tests ()
  """,
  timeout: 300_000
)

returnLettersWithOddCountTests

Test: ReturnLettersWithOddCount

Solution: 1 Test case 1. A. Time: 645L

Solution: 2 Test case 1. A. Time: 663L

Solution: 3 Test case 1. A. Time: 680L

Solution: 9 Test case 1. A. Time: 730L

Solution: 10 Test case 1. A. Time: 815L

Input Expected Result Best
1 a a (1, 645)
2 ba ba (1, 663)
3 aaa aaa (1, 680)
9 aaaaaaaaa aaaaaaaaa (1, 730)
10 baaaaaaaaa baaaaaaaaa (1, 815)

Averages Test case 1. Average Time: 706L

Ranking Test case 1. Average Time: 706L


let solutions = [
    "A",
    fun n ->
        let mutable _builder = StringBuilder (new string('a', n))
        if n % 2 = 0 then
            _builder.[0] <- 'b'

        _builder.ToString ()
]
let testCases = seq {
    1, "a"
    2, "ba"
    3, "aaa"
    9, "aaaaaaaaa"
    10, "baaaaaaaaa"
}
let rec returnLettersWithOddCountTests =
    runAll (nameof returnLettersWithOddCountTests) _count solutions testCases
returnLettersWithOddCountTests
|> sortResultList

hasAnyPairCloseToEachotherTests

Test: HasAnyPairCloseToEachother

Solution: 0 Test case 1. A. Time: 137L

Solution: 1,2 Test case 1. A. Time: 186L

Solution: 3,5 Test case 1. A. Time: 206L

Solution: 3,4,6 Test case 1. A. Time: 149L

Solution: 2,4,6 Test case 1. A. Time: 150L

Input Expected Result Best
0 False False (1, 137)
1,2 True True (1, 186)
3,5 False False (1, 206)
3,4,6 True True (1, 149)
2,4,6 False False (1, 150)

Averages Test case 1. Average Time: 165L

Ranking Test case 1. Average Time: 165L


let solutions = [
    "A",
    fun (a: int[]) ->
        let indices = System.Linq.Enumerable.Range(0, a.Length) |> System.Linq.Enumerable.ToArray
        System.Array.Sort (a, indices)

        indices
        |> Array.take (a.Length - 1)
        |> Array.exists (fun i -> a.[i + 1] - a.[i] = 1)
]
let testCases = seq {
    [| 0 |], false
    [| 1; 2 |], true
    [| 3; 5 |], false
    [| 3; 4; 6 |], true
    [| 2; 4; 6 |], false
}
let rec hasAnyPairCloseToEachotherTests =
    runAll (nameof hasAnyPairCloseToEachotherTests) _count solutions testCases
hasAnyPairCloseToEachotherTests
|> sortResultList