From d277ff078001304352aac27ddebc425be05568bb Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Wed, 5 Jan 2022 23:25:17 +0900
Subject: [PATCH 1/8] Update BinarySearch.fs
---
Algorithms/Search/BinarySearch.fs | 49 +++++++++++--------------------
1 file changed, 17 insertions(+), 32 deletions(-)
diff --git a/Algorithms/Search/BinarySearch.fs b/Algorithms/Search/BinarySearch.fs
index b898582..e34b64e 100644
--- a/Algorithms/Search/BinarySearch.fs
+++ b/Algorithms/Search/BinarySearch.fs
@@ -1,35 +1,20 @@
namespace Algorithms.Search
-open System
-
module BinarySearch =
- let rec byRecursion (sortedData: IComparable [], item: int, left: int, right: int) =
-
- let middle = left + (right - left) / 2
-
- match sortedData.[middle] with
- | s when s.CompareTo(sortedData.[middle]) > item -> byRecursion (sortedData, item, left, middle - 1)
- | s when s.CompareTo(sortedData.[middle]) < item -> byRecursion (sortedData, item, left, middle + 1)
- | _ -> middle
-
- ///
- /// Finds index of item in array that equals to item searched for,
- /// time complexity: O(log(n)),
- /// space complexity: O(1),
- /// where n - array size.
- ///
- /// Sorted array to search in.
- /// Item to search for.
- /// Index of item that equals to item searched for or -1 if none found.
- let rec findIndex (sortedData: IComparable [], item: int) =
-
- let left = 0
- let right = sortedData.Length - 1
-
- let middle = left + (right - left) / 2
- let currentItem = sortedData.[middle]
-
- match currentItem with
- | c when c.CompareTo(sortedData.[middle]) > item -> findIndex (sortedData, item)
- | c when c.CompareTo(sortedData.[middle]) < item -> findIndex (sortedData, item)
- | _ -> item
+ /// Search the target item in a sorted array.
+ /// Returns -1 when the target is not found.
+ /// Time complexity: O(log(sortedData.Length)))
+ let findIndex target sortedData =
+ let rec search l r =
+ let count = r - l
+ let mid = (l + r) / 2
+ let midItem = Array.item mid sortedData
+
+ match count <= 1, compare midItem target with
+ | _, 0 -> mid
+ | true, _ -> -1
+ | false, -1 -> search mid r
+ | false, 1 -> search l mid
+ | _ -> exn () |> raise
+
+ search 0 (Array.length sortedData + 1)
From 7e35a092b2910c9505ac5532b14b2976a950bd08 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Wed, 5 Jan 2022 23:26:17 +0900
Subject: [PATCH 2/8] Add BinarySearchTest.fs
---
Algorithms.Tests/Search/BinarySearchTests.fs | 45 ++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 Algorithms.Tests/Search/BinarySearchTests.fs
diff --git a/Algorithms.Tests/Search/BinarySearchTests.fs b/Algorithms.Tests/Search/BinarySearchTests.fs
new file mode 100644
index 0000000..da999e2
--- /dev/null
+++ b/Algorithms.Tests/Search/BinarySearchTests.fs
@@ -0,0 +1,45 @@
+namespace Algorithms.Tests.Search
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open Algorithms.Search
+
+[]
+type BinarySearchTests() =
+ let data0 =
+ [| -2147483468
+ -10
+ -2
+ -1
+ 0
+ 1
+ 2
+ 10
+ 20
+ 20
+ 2147483467 |]
+
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ member this.Data0_Exists(num: int, expected: int) =
+ let actual = BinarySearch.findIndex num data0
+ Assert.AreEqual(expected, actual)
+
+ []
+ []
+ member this.Data0_Duplicates(num: int) =
+ let actual = BinarySearch.findIndex num data0
+ Assert.IsTrue(actual = 8 || actual = 9)
+
+ []
+ []
+ member this.Data0_None(num: int, expected: int) =
+ let actual = BinarySearch.findIndex num data0
+ Assert.AreEqual(expected, actual)
From 84154909ebd143935fc0390ce296da4bc7532333 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Wed, 5 Jan 2022 23:32:27 +0900
Subject: [PATCH 3/8] Add some functions to Factorial.fs
---
Algorithms/Math/Factorial.fs | 49 +++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/Algorithms/Math/Factorial.fs b/Algorithms/Math/Factorial.fs
index 458b98d..455eb40 100644
--- a/Algorithms/Math/Factorial.fs
+++ b/Algorithms/Math/Factorial.fs
@@ -1,7 +1,48 @@
namespace Algorithms.Math
module Factorial =
- let CalculateFactorial num =
- if (num < 0)
- then failwith "No Factorial for negative numbers"
- else [1..num] |> Seq.fold (fun acc n -> acc * n) 1
\ No newline at end of file
+ /// Calculates factorial. Time complexity: O(n)
+ let byFoldFunction n =
+ if n < 0 then
+ failwith "No factorial for negative numbers"
+ else
+ { 1 .. n } |> Seq.fold (fun acc n -> acc * n) 1
+
+ /// Calculates factorial. Time complexity: O(n)
+ let byReduceFunction n =
+ match n with
+ | n when n < 0 -> failwith "No factorial for negative numbers"
+ | 0 -> 1
+ | n -> { 1 .. n } |> Seq.reduce (*)
+
+ /// Calculates factorial. Time complexity: O(n)
+ let rec byRecursion n =
+ match sign n with
+ | -1 -> failwith "No factorial for negative numbers"
+ | 0 -> 1
+ | _ -> n * byRecursion (n - 1)
+
+ /// Calculates factorial. Time complexity: O(n)
+ let byTailRecursion n =
+ let rec inner n prod =
+ match n with
+ | 0 -> prod
+ | _ -> inner (n - 1) (prod * n)
+
+ match n with
+ | n when n < 0 -> failwith "No factorial for negative numbers"
+ | _ -> inner n 1
+
+ /// Calculates factorial. Time complexity: O(n)
+ let inline byTailRecursionGeneric n =
+ let gen0 = LanguagePrimitives.GenericZero
+ let gen1 = LanguagePrimitives.GenericOne
+
+ let rec inner n prod =
+ match n with
+ | n when n = gen0 -> prod
+ | _ -> inner (n - gen1) (prod * n)
+
+ match n with
+ | n when n < gen0 -> failwith "No factorial for negative numbers"
+ | _ -> inner n gen1
From 23d655bfd9bbd7d67f308e625d977e838b682d88 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Wed, 5 Jan 2022 23:33:23 +0900
Subject: [PATCH 4/8] Increase test cases in FactorialTests.fs
---
Algorithms.Tests/Math/FactorialTests.fs | 51 ++++++++++++++++++++++---
1 file changed, 46 insertions(+), 5 deletions(-)
diff --git a/Algorithms.Tests/Math/FactorialTests.fs b/Algorithms.Tests/Math/FactorialTests.fs
index 5cd15a9..6e3fb23 100644
--- a/Algorithms.Tests/Math/FactorialTests.fs
+++ b/Algorithms.Tests/Math/FactorialTests.fs
@@ -4,15 +4,56 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math
[]
-type FactorialTests () =
-
+type FactorialTests() =
+
[]
+ []
[]
[]
[]
[]
[]
[]
- member this.FactorialOf (num: int, expected: int) =
- let actual = Factorial.CalculateFactorial num
- Assert.AreEqual(expected, actual)
\ No newline at end of file
+ []
+ member this.ValidInt(num: int, expected: int) =
+ seq {
+ Factorial.byFoldFunction
+ Factorial.byReduceFunction
+ Factorial.byRecursion
+ Factorial.byTailRecursion
+ Factorial.byTailRecursionGeneric
+ }
+ |> Seq.iter (fun func ->
+ let actual = func num
+ Assert.AreEqual(expected, actual))
+
+ []
+ []
+ member this.InvalidInt(num: int) =
+ seq {
+ Factorial.byFoldFunction
+ Factorial.byReduceFunction
+ Factorial.byRecursion
+ Factorial.byTailRecursion
+ Factorial.byTailRecursionGeneric
+ }
+ |> Seq.iter (fun func ->
+ let action =
+ new System.Action(fun () -> func num |> ignore)
+
+ Assert.ThrowsException(action) |> ignore)
+
+ []
+ member this.Generic() =
+ Assert.AreEqual(479001600, Factorial.byTailRecursionGeneric 12)
+ Assert.AreEqual(479001600u, Factorial.byTailRecursionGeneric 12u)
+ Assert.AreEqual(479001600.f, Factorial.byTailRecursionGeneric 12.f)
+ Assert.AreEqual(2432902008176640000L, Factorial.byTailRecursionGeneric 20L)
+ Assert.AreEqual(2432902008176640000UL, Factorial.byTailRecursionGeneric 20UL)
+ Assert.AreEqual(2432902008176640000., Factorial.byTailRecursionGeneric 20.)
+ Assert.AreEqual(10888869450418352160768000000M, Factorial.byTailRecursionGeneric 27M)
+
+ Assert.AreEqual(
+ 30414093201713378043612608166064768844377641568960512000000000000I,
+ Factorial.byTailRecursionGeneric 50I
+ )
From 8229192ac723f232411e41d78b372cc508417165 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Thu, 6 Jan 2022 00:09:10 +0900
Subject: [PATCH 5/8] Rename and improve complexity of isPerfect
---
Algorithms.Tests/Math/PerfectNumbersTests.fs | 10 +++++-----
Algorithms/Math/PerfectNumbers.fs | 13 +++++++++++++
Algorithms/Math/Perfect_Numbers.fs | 13 -------------
3 files changed, 18 insertions(+), 18 deletions(-)
create mode 100644 Algorithms/Math/PerfectNumbers.fs
delete mode 100644 Algorithms/Math/Perfect_Numbers.fs
diff --git a/Algorithms.Tests/Math/PerfectNumbersTests.fs b/Algorithms.Tests/Math/PerfectNumbersTests.fs
index df3a07b..46dc516 100644
--- a/Algorithms.Tests/Math/PerfectNumbersTests.fs
+++ b/Algorithms.Tests/Math/PerfectNumbersTests.fs
@@ -4,8 +4,8 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math
[]
-type PerfectNumbersTests () =
-
+type PerfectNumbersTests() =
+
[]
[]
[]
@@ -22,6 +22,6 @@ type PerfectNumbersTests () =
[]
[]
[]
- member this.IsPerfect (n: int, expected: bool) =
- let actual = Perfect_Numbers.IsPerfect n
- Assert.AreEqual(expected, actual)
\ No newline at end of file
+ member this.Test(n: int, expected: bool) =
+ let actual = PerfectNumbers.isPerfect n
+ Assert.AreEqual(expected, actual)
diff --git a/Algorithms/Math/PerfectNumbers.fs b/Algorithms/Math/PerfectNumbers.fs
new file mode 100644
index 0000000..459fc60
--- /dev/null
+++ b/Algorithms/Math/PerfectNumbers.fs
@@ -0,0 +1,13 @@
+namespace Algorithms.Math
+
+module PerfectNumbers =
+ /// Check if a number is perfect. Time complexity: O(√n)
+ let isPerfect n =
+ match n with
+ | n when n <= 0 -> false
+ | n ->
+ { 1 .. n - 1 }
+ |> Seq.takeWhile (fun i -> i * i <= n)
+ |> Seq.filter ((%) n >> (=) 0)
+ |> Seq.fold (fun acc i -> acc + i + n / i) 0
+ |> (=) (2 * n)
diff --git a/Algorithms/Math/Perfect_Numbers.fs b/Algorithms/Math/Perfect_Numbers.fs
deleted file mode 100644
index 27f2230..0000000
--- a/Algorithms/Math/Perfect_Numbers.fs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace Algorithms.Math
-
-module Perfect_Numbers =
- let IsPerfect (number: int) =
- match number with
- | number when number <= 0 -> false
- | number ->
- let total =
- seq { 1 .. number - 1 }
- |> Seq.filter (fun n -> number % n = 0)
- |> Seq.sum
-
- total = number
From 4c1329a48ebfab3fc2d8ad68f29ab31ace4c6245 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Thu, 6 Jan 2022 00:18:31 +0900
Subject: [PATCH 6/8] update Power.fs and its tests
---
Algorithms.Tests/Math/PowerTests.fs | 55 ++++++++++++++++++++++++++---
Algorithms/Math/Power.fs | 19 ++++++++--
2 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/Algorithms.Tests/Math/PowerTests.fs b/Algorithms.Tests/Math/PowerTests.fs
index c583641..2d049cc 100644
--- a/Algorithms.Tests/Math/PowerTests.fs
+++ b/Algorithms.Tests/Math/PowerTests.fs
@@ -4,9 +4,10 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math
[]
-type PowerTests () =
-
+type PowerTests() =
+
[]
+ []
[]
[]
[]
@@ -17,6 +18,50 @@ type PowerTests () =
[]
[]
[]
- member this.PowerOf (num: int, pow: int, expected: int) =
- let actual = Power.Pow num pow
- Assert.AreEqual(expected, actual)
\ No newline at end of file
+ member this.FoldFunction_Valid(num: int, pow: int, expected: int) =
+ let actual = Power.byFoldFunction num pow
+ Assert.AreEqual(expected, actual)
+
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ member this.ByRecursion_Valid(num: int, pow: int, expected: int) =
+ let actual = Power.byRecursion num pow
+ Assert.AreEqual(expected, actual)
+
+ []
+ []
+ []
+ member this.ByRecursion_Invalid(num: int, pow: int) =
+ let action =
+ new System.Action(fun () -> Power.byRecursion num pow |> ignore)
+
+ Assert.ThrowsException(action)
+ |> ignore
diff --git a/Algorithms/Math/Power.fs b/Algorithms/Math/Power.fs
index 895826b..253a28f 100644
--- a/Algorithms/Math/Power.fs
+++ b/Algorithms/Math/Power.fs
@@ -1,5 +1,20 @@
namespace Algorithms.Math
module Power =
- let Pow x powerOf =
- [1..powerOf] |> Seq.fold (fun acc _ -> acc * x) 1
\ No newline at end of file
+ /// Calculates x^n. Time complexity: O(√n).
+ let byFoldFunction x n =
+ { 1 .. n } |> Seq.fold (fun acc _ -> acc * x) 1
+
+ /// Calculates x^n. x and n can be negative.
+ /// Time complexity O(n).
+ let rec byRecursion x n =
+ match x, sign n with
+ | 0, -1 ->
+ System.DivideByZeroException "Attempted to divide by zero."
+ |> raise
+ | -1, _ -> if n % 2 = 0 then 1 else -1
+ | 1, _ -> 1
+ | _, 0 -> 1
+ | 0, _ -> 0
+ | _, -1 -> 0
+ | _, _ -> x * byRecursion x (n - 1)
From 0eafd474be2e87407be8a6a8c32ed1015341d075 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Thu, 6 Jan 2022 00:23:38 +0900
Subject: [PATCH 7/8] Add Prime and its tests
---
Algorithms.Tests/Math/PrimeTests.fs | 22 ++++++++++++++++++++++
Algorithms/Math/Prime.fs | 20 ++++++++++++++++++++
2 files changed, 42 insertions(+)
create mode 100644 Algorithms.Tests/Math/PrimeTests.fs
create mode 100644 Algorithms/Math/Prime.fs
diff --git a/Algorithms.Tests/Math/PrimeTests.fs b/Algorithms.Tests/Math/PrimeTests.fs
new file mode 100644
index 0000000..4abb0fe
--- /dev/null
+++ b/Algorithms.Tests/Math/PrimeTests.fs
@@ -0,0 +1,22 @@
+namespace Algorithms.Tests.Math
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open Algorithms.Math
+
+[]
+type PrimeTests() =
+
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ []
+ member this.IsPrime(input: int, expected: bool) =
+ let actual = Prime.isPrime input
+ Assert.AreEqual(expected, actual)
diff --git a/Algorithms/Math/Prime.fs b/Algorithms/Math/Prime.fs
new file mode 100644
index 0000000..38c65ab
--- /dev/null
+++ b/Algorithms/Math/Prime.fs
@@ -0,0 +1,20 @@
+namespace Algorithms.Math
+
+module Prime =
+ /// Check if a number is prime. Time complexity: O(√n)
+ let isPrime n =
+ if n <= 1 then
+ false
+ elif n = 2 then
+ true
+ elif n % 2 = 0 then
+ false
+ else
+ seq {
+ let mutable i = 3
+
+ while i * i <= n do
+ yield i
+ i <- i + 2
+ }
+ |> Seq.forall ((%) n >> (<>) 0)
From 8cef8117b60f659b8764f6508c15ef76e3ce94e3 Mon Sep 17 00:00:00 2001
From: i1e0 <96235137+i1e0@users.noreply.github.com>
Date: Thu, 6 Jan 2022 00:24:09 +0900
Subject: [PATCH 8/8] Add tests for math functions
---
Algorithms.Tests/Math/AbsMaxTests.fs | 13 +++++++++++++
Algorithms.Tests/Math/AbsMinTests.fs | 13 +++++++++++++
Algorithms.Tests/Math/AbsTests.fs | 17 +++++++++++++++++
3 files changed, 43 insertions(+)
create mode 100644 Algorithms.Tests/Math/AbsMaxTests.fs
create mode 100644 Algorithms.Tests/Math/AbsMinTests.fs
create mode 100644 Algorithms.Tests/Math/AbsTests.fs
diff --git a/Algorithms.Tests/Math/AbsMaxTests.fs b/Algorithms.Tests/Math/AbsMaxTests.fs
new file mode 100644
index 0000000..5fd9ec1
--- /dev/null
+++ b/Algorithms.Tests/Math/AbsMaxTests.fs
@@ -0,0 +1,13 @@
+namespace Algorithms.Tests.Math
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open Algorithms.Math
+
+[]
+type AbsMaxTests() =
+
+ []
+ member this.Test() =
+ Assert.AreEqual(-3, AbsMax.absMax [ -1; 1; 2; -2; -3; 3 ])
+ Assert.AreEqual(3, AbsMax.absMax [ 1; -1; 2; -2; 3; -3 ])
+ Assert.AreEqual(-1, AbsMax.absMax [ 0; -1; 0 ])
diff --git a/Algorithms.Tests/Math/AbsMinTests.fs b/Algorithms.Tests/Math/AbsMinTests.fs
new file mode 100644
index 0000000..e39b215
--- /dev/null
+++ b/Algorithms.Tests/Math/AbsMinTests.fs
@@ -0,0 +1,13 @@
+namespace Algorithms.Tests.Math
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open Algorithms.Math
+
+[]
+type AbsMinTests() =
+
+ []
+ member this.Test() =
+ Assert.AreEqual(-1, AbsMin.absMin [ -1; 1; 2; -2; -3; 3 ])
+ Assert.AreEqual(1, AbsMin.absMin [ 1; -1; 2; -2; 3; -3 ])
+ Assert.AreEqual(0, AbsMin.absMin [ 0; -1; 0 ])
diff --git a/Algorithms.Tests/Math/AbsTests.fs b/Algorithms.Tests/Math/AbsTests.fs
new file mode 100644
index 0000000..9dfec5b
--- /dev/null
+++ b/Algorithms.Tests/Math/AbsTests.fs
@@ -0,0 +1,17 @@
+namespace Algorithms.Tests.Math
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open Algorithms.Math
+
+[]
+type AbsTests() =
+
+ []
+ []
+ []
+ []
+ []
+ []
+ member this.Test(input: int, expected: int) =
+ let actual = Abs.absVal input
+ Assert.AreEqual(expected, actual)