#!meta {"kernelInfo":{"defaultKernelName":"spiral","items":[{"aliases":[],"name":"spiral"}]}} #!markdown # Perf (Polyglot) #!fsharp #!import ../../lib/fsharp/Notebooks.dib #!import ../../lib/fsharp/Testing.dib #!spiral //// test open testing open benchmark #!fsharp #if !INTERACTIVE open Lib #endif #!markdown ## TestCaseResult #!fsharp type TestCaseResult = { Input: string Expected: string Result: string TimeList: int64 list } #!markdown ## run #!fsharp 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 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 } #!markdown ## runAll #!fsharp let runAll testName count (solutions: (string * ('TInput -> 'TExpected)) list) testCases = printfn "" printfn "" printfn $"Test: {testName}" testCases |> Seq.map (run count solutions) |> Seq.toList #!markdown ## sortResultList #!fsharp 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} " ) #!fsharp let mutable _count = if ("CI" |> System.Environment.GetEnvironmentVariable |> fun x -> $"%A{x}") <> "" then 2000000 else 2000 #!spiral inl is_fast () = false #!markdown ## empty3Tests #!markdown 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 #!fsharp //// test 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 #!markdown ## empty2Tests #!markdown 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 #!fsharp //// test 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 #!markdown ## emptyTests #!markdown 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 #!fsharp //// test 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 #!markdown ## uniqueLettersTests #!markdown 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 #!fsharp //// test 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 loop set = function | head :: tail when Set.contains head set -> loop set tail | head :: tail -> (loop (set.Add head) tail) @ [ head ] | [] -> [] loop Set.empty list |> List.rev |> List.toArray |> String "I", fun input -> input |> Seq.toList |> fun list -> let rec loop set = function | head :: tail when Set.contains head set -> loop set tail | head :: tail -> loop (set.Add head) tail |> Array.append [| head |] | [] -> [||] loop Set.empty list |> String "J", fun input -> input |> Seq.toList |> fun list -> let rec loop set = function | head :: tail when Set.contains head set -> loop set tail | head :: tail -> head :: loop (set.Add head) tail | [] -> [] loop 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 #!markdown ## rotateStringsTests #!markdown 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 #!fsharp //// test 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 loop (acc: char list list) = function | _ when acc.Length = list.Length -> acc | head :: tail -> let item = tail @ [ head ] loop (item :: acc) item | [] -> [] loop [] list |> List.rev |> List.map (List.toArray >> String) |> SpiralSm.concat " " "E", fun input -> input |> Seq.toList |> fun list -> let rec loop (last: string) = function | head :: tail -> let item = last.[1 .. input.Length - 1] + string head item :: loop item tail | [] -> [] loop 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 #!markdown ## rotate_strings_tests #!markdown ``` 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 //// test //// timeout=60000 inl get_solutions () = [ // "A", // fun (input : string) => // let resultList = // List.fold (fun acc x => // let rotate (text : string) (letter : string) = text.Substring (1, input.Length - 1) + letter // [ rotate (if acc.IsEmpty then input else acc.Head) (string x) ] ++ acc // ) [] (Seq.toList input) // List.foldBack (fun acc x => x + acc + " ") resultList "" // |> fun x => x.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 : list string) 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 : list string) 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 : a _ string) letter => acc |> Array.append (a ;[ acc.[0].[ 1 .. input.Length - 1 ] + string letter ])) (a ;[ input ]) // |> Array.rev // |> Array.skip 1 // |> SpiralSm.concat " " // "D", // fun input => // input // |> Seq.toList // |> fun list => // let rec loop (acc : list (list char)) = function // | _ when acc.Length = list.Length => acc // | head :: tail => // let item = tail ++ [ head ] // loop (item :: acc) item // | [] => [] // loop [] list // |> List.rev // |> List.map (List.toArray >> String) // |> SpiralSm.concat " " // "E", // fun input => // input // |> Seq.toList // |> fun list => // let rec loop (last : string) = function // | head :: tail => // let item = last.[1 .. input.Length - 1] + string head // item :: loop item tail // | [] => [] // loop 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 " " inl input_length = input |> sm.length am.singleton 0i32 |> am.append (am'.init_series 1 (input_length - 1) 1 |> fun x => a x : _ int _) |> fun (a x) => x |> am'.map_base fun i => inl a = input |> sm'.slice i (input_length - 1) inl b = input |> sm'.slice 0 (i - 1) a +. b |> fun x => a x : _ int _ |> seq.of_array |> sm'.concat " " "FA", fun input => // List.singleton 0 // |> List.append [ 1 .. input.Length - 1 ] // // |> List.map (fun i => input.[ i .. ] + input.[ .. i - 1 ]) // |> SpiralSm.concat " " 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) a +. b ) |> listm'.box |> listm'.to_array' |> fun x => a x : _ int _ |> seq.of_array |> sm'.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 (a ;[ 1 .. input.Length - 1 ]) //// |> Array.Parallel.map (fun i => input.[ i .. ] + input.[ .. i - 1 ]) // |> SpiralSm.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 is_fast () = true 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 () #!spiral //// test // rotate_strings_tests () () #!markdown ## binary_search_tests #!markdown ``` 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 //// test //// timeout=90000 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 loop (mid + 1) right else loop left mid and inl loop left right = if var_is right |> not then body left right else inl left = dyn left join body left right loop 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 loop (mid + 1) right else loop left (mid - 1) and inl loop left right = if var_is right |> not then body left right else inl left = dyn left join body left right loop 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 loop (mid + 1) right else loop left mid and inl loop left right = body left right loop 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 loop (mid + 1) right else loop left (mid - 1) and inl loop left right = body left right loop 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 = [ (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 6 None), (Some 3i32) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 1 None), (Some 0i32) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 11 None), (Some 6i32) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 12 None), None ((am'.init_series 1i32 1000 1 |> fun x => a x : _ int _) |> arr_with_len 60 None), (Some 59) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 6 (Some 7)), (Some 3i32) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 1 (Some 7)), (Some 0i32) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 11 (Some 7)), (Some 6i32) (a ;[ 1i32; 3; 4; 6; 8; 9; 11 ] |> arr_with_len 12 (Some 7)), None ((am'.init_series 1i32 1000 1 |> fun x => a x : _ int _) |> arr_with_len 60 (Some 100)), (Some 59) ] inl solutions = get_solutions () // inl is_fast () = true 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 () #!markdown ## returnLettersWithOddCountTests #!markdown 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 #!fsharp //// test 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 #!markdown ## hasAnyPairCloseToEachotherTests #!markdown 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 #!fsharp //// test 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