Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Algorithms.Tests/Math/AbsMaxTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Algorithms.Tests.Math

open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type AbsMaxTests() =

[<TestMethod>]
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 ])
13 changes: 13 additions & 0 deletions Algorithms.Tests/Math/AbsMinTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Algorithms.Tests.Math

open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type AbsMinTests() =

[<TestMethod>]
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 ])
17 changes: 17 additions & 0 deletions Algorithms.Tests/Math/AbsTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Algorithms.Tests.Math

open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type AbsTests() =

[<TestMethod>]
[<DataRow(-10, 10)>]
[<DataRow(-1, 1)>]
[<DataRow(0, 0)>]
[<DataRow(1, 1)>]
[<DataRow(10, 10)>]
member this.Test(input: int, expected: int) =
let actual = Abs.absVal input
Assert.AreEqual(expected, actual)
51 changes: 46 additions & 5 deletions Algorithms.Tests/Math/FactorialTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,56 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type FactorialTests () =
type FactorialTests() =

[<TestMethod>]
[<DataRow(0, 1)>]
[<DataRow(1, 1)>]
[<DataRow(2, 2)>]
[<DataRow(3, 6)>]
[<DataRow(5, 120)>]
[<DataRow(8, 40320)>]
[<DataRow(10, 3628800)>]
member this.FactorialOf (num: int, expected: int) =
let actual = Factorial.CalculateFactorial num
Assert.AreEqual(expected, actual)
[<DataRow(12, 479001600)>]
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))

[<TestMethod>]
[<DataRow(-1)>]
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)

[<TestMethod>]
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
)
10 changes: 5 additions & 5 deletions Algorithms.Tests/Math/PerfectNumbersTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type PerfectNumbersTests () =
type PerfectNumbersTests() =

[<TestMethod>]
[<DataRow(-1, false)>]
[<DataRow(0, false)>]
Expand All @@ -22,6 +22,6 @@ type PerfectNumbersTests () =
[<DataRow(8128, true)>]
[<DataRow(33550336, true)>]
[<DataRow(33550337, false)>]
member this.IsPerfect (n: int, expected: bool) =
let actual = Perfect_Numbers.IsPerfect n
Assert.AreEqual(expected, actual)
member this.Test(n: int, expected: bool) =
let actual = PerfectNumbers.isPerfect n
Assert.AreEqual(expected, actual)
55 changes: 50 additions & 5 deletions Algorithms.Tests/Math/PowerTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type PowerTests () =
type PowerTests() =

[<TestMethod>]
[<DataRow(0, 100, 0)>]
[<DataRow(2, 2, 4)>]
[<DataRow(2, 3, 8)>]
[<DataRow(2, 4, 16)>]
Expand All @@ -17,6 +18,50 @@ type PowerTests () =
[<DataRow(10, 4, 10000)>]
[<DataRow(1, 2, 1)>]
[<DataRow(1, 50, 1)>]
member this.PowerOf (num: int, pow: int, expected: int) =
let actual = Power.Pow num pow
Assert.AreEqual(expected, actual)
member this.FoldFunction_Valid(num: int, pow: int, expected: int) =
let actual = Power.byFoldFunction num pow
Assert.AreEqual(expected, actual)

[<TestMethod>]
[<DataRow(-2, -2, 0)>]
[<DataRow(-2, -1, 0)>]
[<DataRow(-2, 0, 1)>]
[<DataRow(-2, 1, -2)>]
[<DataRow(-2, 2, 4)>]
[<DataRow(-2, 3, -8)>]
[<DataRow(-1, -3, -1)>]
[<DataRow(-1, -2, 1)>]
[<DataRow(-1, -1, -1)>]
[<DataRow(-1, 0, 1)>]
[<DataRow(-1, 1, -1)>]
[<DataRow(-1, 2, 1)>]
[<DataRow(-1, 3, -1)>]
[<DataRow(0, 0, 1)>]
[<DataRow(0, 1, 0)>]
[<DataRow(0, 2, 0)>]
[<DataRow(1, -2, 1)>]
[<DataRow(1, -1, 1)>]
[<DataRow(1, 0, 1)>]
[<DataRow(1, 1, 1)>]
[<DataRow(1, 2, 1)>]
[<DataRow(2, 2, 4)>]
[<DataRow(2, 3, 8)>]
[<DataRow(2, 4, 16)>]
[<DataRow(2, 8, 256)>]
[<DataRow(2, 16, 65536)>]
[<DataRow(3, 5, 243)>]
[<DataRow(5, 3, 125)>]
[<DataRow(10, 4, 10000)>]
member this.ByRecursion_Valid(num: int, pow: int, expected: int) =
let actual = Power.byRecursion num pow
Assert.AreEqual(expected, actual)

[<TestMethod>]
[<DataRow(0, -1)>]
[<DataRow(0, -2)>]
member this.ByRecursion_Invalid(num: int, pow: int) =
let action =
new System.Action(fun () -> Power.byRecursion num pow |> ignore)

Assert.ThrowsException<System.DivideByZeroException>(action)
|> ignore
22 changes: 22 additions & 0 deletions Algorithms.Tests/Math/PrimeTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Algorithms.Tests.Math

open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Math

[<TestClass>]
type PrimeTests() =

[<TestMethod>]
[<DataRow(-3, false)>]
[<DataRow(-2, false)>]
[<DataRow(-1, false)>]
[<DataRow(0, false)>]
[<DataRow(1, false)>]
[<DataRow(2, true)>]
[<DataRow(49, false)>]
[<DataRow(50, false)>]
[<DataRow(998244353, true)>]
[<DataRow(1000000007, true)>]
member this.IsPrime(input: int, expected: bool) =
let actual = Prime.isPrime input
Assert.AreEqual(expected, actual)
45 changes: 45 additions & 0 deletions Algorithms.Tests/Search/BinarySearchTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace Algorithms.Tests.Search

open Microsoft.VisualStudio.TestTools.UnitTesting
open Algorithms.Search

[<TestClass>]
type BinarySearchTests() =
let data0 =
[| -2147483468
-10
-2
-1
0
1
2
10
20
20
2147483467 |]

[<TestMethod>]
[<DataRow(-2147483468, 0)>]
[<DataRow(-10, 1)>]
[<DataRow(-2, 2)>]
[<DataRow(-1, 3)>]
[<DataRow(0, 4)>]
[<DataRow(1, 5)>]
[<DataRow(2, 6)>]
[<DataRow(10, 7)>]
[<DataRow(2147483467, 10)>]
member this.Data0_Exists(num: int, expected: int) =
let actual = BinarySearch.findIndex num data0
Assert.AreEqual(expected, actual)

[<TestMethod>]
[<DataRow(20)>]
member this.Data0_Duplicates(num: int) =
let actual = BinarySearch.findIndex num data0
Assert.IsTrue(actual = 8 || actual = 9)

[<TestMethod>]
[<DataRow(5, -1)>]
member this.Data0_None(num: int, expected: int) =
let actual = BinarySearch.findIndex num data0
Assert.AreEqual(expected, actual)
49 changes: 45 additions & 4 deletions Algorithms/Math/Factorial.fs
Original file line number Diff line number Diff line change
@@ -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
/// 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
13 changes: 13 additions & 0 deletions Algorithms/Math/PerfectNumbers.fs
Original file line number Diff line number Diff line change
@@ -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)
13 changes: 0 additions & 13 deletions Algorithms/Math/Perfect_Numbers.fs

This file was deleted.

19 changes: 17 additions & 2 deletions Algorithms/Math/Power.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
namespace Algorithms.Math

module Power =
let Pow x powerOf =
[1..powerOf] |> Seq.fold (fun acc _ -> acc * x) 1
/// 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)
20 changes: 20 additions & 0 deletions Algorithms/Math/Prime.fs
Original file line number Diff line number Diff line change
@@ -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)
Loading