diff --git a/.build/Bootstrap.ps1 b/.build/Bootstrap.ps1
index 37b49cbe..4d77d2bd 100644
--- a/.build/Bootstrap.ps1
+++ b/.build/Bootstrap.ps1
@@ -14,7 +14,7 @@ Install-Psake
$psakeDirectory = (Resolve-Path $env:ChocolateyInstall\lib\Psake*)
-Import-Module (Join-Path $psakeDirectory "tools\Psake.psm1")
+Import-Module (Join-Path $psakeDirectory "tools\Psake\Psake.psm1")
if($Help)
{
diff --git a/.build/Common.psm1 b/.build/Common.psm1
index b73c1d9d..1a19d515 100644
--- a/.build/Common.psm1
+++ b/.build/Common.psm1
@@ -24,7 +24,7 @@ function Install-Chocolatey()
function Install-Psake()
{
- if(!(Test-Path $env:ChocolateyInstall\lib\Psake*))
+ if(!(Test-Path $env:ChocolateyInstall\lib\Psake\tools\Psake*))
{
choco install psake -y
}
diff --git a/.build/default.ps1 b/.build/default.ps1
index 2507709d..46263cf3 100644
--- a/.build/default.ps1
+++ b/.build/default.ps1
@@ -54,7 +54,7 @@ Task Restore-Packages {
}
Task Install-MSBuild {
- if(!(Test-Path $MSBuild14))
+ if(!(Test-Path $MSBuild))
{
cinst microsoft-build-tools -y
}
diff --git a/Advanced.Algorithms.Tests/Advanced.Algorithms.Tests.csproj b/Advanced.Algorithms.Tests/Advanced.Algorithms.Tests.csproj
index 2d35c843..1efa7396 100644
--- a/Advanced.Algorithms.Tests/Advanced.Algorithms.Tests.csproj
+++ b/Advanced.Algorithms.Tests/Advanced.Algorithms.Tests.csproj
@@ -67,7 +67,6 @@
-
@@ -99,7 +98,7 @@
-
+
@@ -126,7 +125,10 @@
+
+
+
diff --git a/Advanced.Algorithms.Tests/Combinatorics/Permutation_Tests.cs b/Advanced.Algorithms.Tests/Combinatorics/Permutation_Tests.cs
index 5e066128..d3cdd420 100644
--- a/Advanced.Algorithms.Tests/Combinatorics/Permutation_Tests.cs
+++ b/Advanced.Algorithms.Tests/Combinatorics/Permutation_Tests.cs
@@ -12,77 +12,64 @@ namespace Advanced.Algorithms.Tests.Combinatorics
public class Permutation_Tests
{
//for verification
- readonly Func factorial = n => n == 0 ? 1 :
+ static readonly Func factorial = n => n == 0 ? 1 :
Enumerable.Range(1, n).Aggregate((acc, x) => acc * x);
-
- [TestMethod]
- public void Permutation_Without_Repetitions_Smoke_Test()
- {
- var input = "".ToCharArray().ToList();
- var permuations = Permutation.Find(input);
- Assert.AreEqual(factorial(input.Count), permuations.Count);
-
- input = "cookie".ToCharArray().ToList();
- permuations = Permutation.Find(input);
- Assert.AreEqual(factorial(input.Count), permuations.Count);
-
- input = "monster".ToCharArray().ToList();
- permuations = Permutation.Find(input);
- Assert.AreEqual(factorial(input.Count), permuations.Count);
- }
-
+ //for verification
+ static readonly Func permutation = (int n, int r)
+ => n == 0 || r == 0 ? 1 : factorial(n) / factorial(n - r);
[TestMethod]
public void Permutation_With_Repetition_Smoke_Test()
{
var input = "".ToCharArray().ToList();
- var permuations = Permutation.Find(input, true);
+ var permuations = Permutation.Find(input, input.Count, true);
Assert.AreEqual(Math.Pow(input.Count, input.Count), permuations.Count);
input = "pen".ToCharArray().ToList();
- permuations = Permutation.Find(input, true);
+ permuations = Permutation.Find(input, input.Count, true);
Assert.AreEqual(Math.Pow(input.Count, input.Count), permuations.Count);
input = "scan".ToCharArray().ToList();
- permuations = Permutation.Find(input, true);
+ permuations = Permutation.Find(input, input.Count, true);
Assert.AreEqual(Math.Pow(input.Count, input.Count), permuations.Count);
- }
- [TestMethod]
- public void Permutation_Without_Repetition_Without_Inversions_Smoke_Test()
- {
- var input = "".ToCharArray().ToList();
- var permuations = Permutation.Find(input, false, false);
- Assert.AreEqual(factorial(input.Count) / 2, permuations.Count);
+ input = "scan".ToCharArray().ToList();
+ permuations = Permutation.Find(input, 2, true);
+ Assert.AreEqual(Math.Pow(input.Count, 2), permuations.Count);
- input = "abc".ToCharArray().ToList();
- permuations = Permutation.Find(input, false, false);
- Assert.AreEqual(factorial(input.Count) / 2, permuations.Count);
+ input = "scan".ToCharArray().ToList();
+ permuations = Permutation.Find(input, 3, true);
+ Assert.AreEqual(Math.Pow(input.Count, 3), permuations.Count);
- input = "acde".ToCharArray().ToList();
- permuations = Permutation.Find(input, false, false);
- Assert.AreEqual(factorial(input.Count) / 2, permuations.Count);
+ input = "scaner".ToCharArray().ToList();
+ permuations = Permutation.Find(input, 4, true);
+ Assert.AreEqual(Math.Pow(input.Count, 4), permuations.Count);
}
[TestMethod]
- public void Permutation_With_Repetition_Without_Inversions_Smoke_Test()
+ public void Permutation_Without_Repetitions_Smoke_Test()
{
-
var input = "".ToCharArray().ToList();
- var permuations = Permutation.Find(input, true, false);
- Assert.AreEqual(0, permuations.Count);
+ var permuations = Permutation.Find(input, input.Count);
+ Assert.AreEqual(permutation(input.Count, input.Count), permuations.Count);
- input = "pen".ToCharArray().ToList();
- permuations = Permutation.Find(input, true, false);
- Assert.AreEqual(9, permuations.Count);
+ input = "cookie".ToCharArray().ToList();
+ permuations = Permutation.Find(input, input.Count);
+ Assert.AreEqual(permutation(input.Count, input.Count), permuations.Count);
- input = "cool".ToCharArray().ToList();
- permuations = Permutation.Find(input, true, false);
- Assert.AreEqual(80, permuations.Count);
- }
+ input = "monster".ToCharArray().ToList();
+ permuations = Permutation.Find(input, input.Count);
+ Assert.AreEqual(permutation(input.Count, input.Count), permuations.Count);
-
+ input = "cookie".ToCharArray().ToList();
+ permuations = Permutation.Find(input, 2);
+ Assert.AreEqual(permutation(input.Count, 2), permuations.Count);
+
+ input = "monster".ToCharArray().ToList();
+ permuations = Permutation.Find(input, 3);
+ Assert.AreEqual(permutation(input.Count, 3), permuations.Count);
+ }
}
}
diff --git a/Advanced.Algorithms.Tests/Combinatorics/Variation_Tests.cs b/Advanced.Algorithms.Tests/Combinatorics/Variation_Tests.cs
deleted file mode 100644
index f0d3604b..00000000
--- a/Advanced.Algorithms.Tests/Combinatorics/Variation_Tests.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Advanced.Algorithms.Combinatorics;
-
-namespace Advanced.Algorithms.Tests.Combinatorics
-{
- [TestClass]
- public class Variation_Tests
- {
- //for verification
- static readonly Func factorial = n => n == 0 ? 1 :
- Enumerable.Range(1, n).Aggregate((acc, x) => acc * x);
-
- //for verification
- static readonly Func combination = (int n, int r)
- => n == 0 || r == 0 ? 0 : factorial(n) / (factorial(r) * factorial(n - r));
-
- [TestMethod]
- public void Variation_Without_Repetitions_Smoke_Test()
- {
- var input = "".ToCharArray().ToList();
- var variations = Variation.Find(input, 2, false);
- Assert.AreEqual(combination(input.Count, 2) * factorial(2), variations.Count);
-
- input = "cookie".ToCharArray().ToList();
- variations = Variation.Find(input, 3, false);
- Assert.AreEqual(combination(input.Count, 3) * factorial(3), variations.Count);
-
- input = "monsters".ToCharArray().ToList();
- variations = Variation.Find(input, 3, false);
- Assert.AreEqual(combination(input.Count, 3) * factorial(3), variations.Count);
- }
-
-
- [TestMethod]
- public void Variation_With_Repetitions_Smoke_Test()
- {
- var input = "abcd".ToCharArray().ToList();
- var variations = Variation.Find(input, 2, true);
- Assert.AreEqual(Math.Pow(input.Count, 2), variations.Count);
-
- input = "scan".ToCharArray().ToList();
- variations = Variation.Find(input, 3, true);
- Assert.AreEqual(Math.Pow(input.Count, 3), variations.Count);
-
- input = "".ToCharArray().ToList();
- variations = Variation.Find(input, 3, true);
- Assert.AreEqual(0, variations.Count);
- }
-
- }
-}
diff --git a/Advanced.Algorithms.Tests/DataStructures/Queues/CircularQueue_Tests.cs b/Advanced.Algorithms.Tests/DistributedSystems/CircularQueue_Tests.cs
similarity index 62%
rename from Advanced.Algorithms.Tests/DataStructures/Queues/CircularQueue_Tests.cs
rename to Advanced.Algorithms.Tests/DistributedSystems/CircularQueue_Tests.cs
index eecd152d..d68a3411 100644
--- a/Advanced.Algorithms.Tests/DataStructures/Queues/CircularQueue_Tests.cs
+++ b/Advanced.Algorithms.Tests/DistributedSystems/CircularQueue_Tests.cs
@@ -1,8 +1,7 @@
-using Advanced.Algorithms.DataStructures;
-using Advanced.Algorithms.DataStructures.Queues;
+using Advanced.Algorithms.DataStructures.DistributedSystems;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-namespace Advanced.Algorithms.Tests.DataStructures.Queues
+namespace Advanced.Algorithms.Tests.DataStructures.DistributedSystems
{
[TestClass]
public class CircularQueue_Tests
@@ -13,16 +12,16 @@ public void CircularQueue_Test()
{
var Queue = new CircularQueue(7);
- Queue.Enqueue(1);
- Queue.Enqueue(2);
+ Assert.AreEqual(0, Queue.Enqueue(1));
+ Assert.AreEqual(0, Queue.Enqueue(2));
- Queue.Enqueue(3);
- Queue.Enqueue(4);
- Queue.Enqueue(5);
- Queue.Enqueue(6);
- Queue.Enqueue(7);
- Queue.Enqueue(8);
- Queue.Enqueue(9);
+ Assert.AreEqual(0, Queue.Enqueue(3));
+ Assert.AreEqual(0, Queue.Enqueue(4));
+ Assert.AreEqual(0, Queue.Enqueue(5));
+ Assert.AreEqual(0, Queue.Enqueue(6));
+ Assert.AreEqual(0, Queue.Enqueue(7));
+ Assert.AreEqual(1, Queue.Enqueue(8));
+ Assert.AreEqual(2, Queue.Enqueue(9));
Assert.AreEqual(Queue.Count, 7);
Assert.AreEqual(3, Queue.Dequeue());
@@ -47,8 +46,8 @@ public void CircularQueue_Test()
Assert.AreEqual(Queue.Count, 0);
- Queue.Enqueue(1);
- Queue.Enqueue(2);
+ Assert.AreEqual(0, Queue.Enqueue(1));
+ Assert.AreEqual(0, Queue.Enqueue(2));
Assert.AreEqual(Queue.Count, 2);
Assert.AreEqual(1, Queue.Dequeue());
@@ -57,6 +56,6 @@ public void CircularQueue_Test()
Assert.AreEqual(Queue.Dequeue(), 2);
}
-
+
}
-}
+}
\ No newline at end of file
diff --git a/Advanced.Algorithms.Tests/DistributedSystems/ConsistentHash_Tests.cs b/Advanced.Algorithms.Tests/DistributedSystems/ConsistentHash_Tests.cs
new file mode 100644
index 00000000..fabd438a
--- /dev/null
+++ b/Advanced.Algorithms.Tests/DistributedSystems/ConsistentHash_Tests.cs
@@ -0,0 +1,43 @@
+using Advanced.Algorithms.DistributedSystems;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+
+namespace Advanced.Algorithms.Tests.DistributedSystems
+{
+ [TestClass]
+ public class ConsistentHash_Tests
+ {
+
+ [TestMethod]
+ public void ConsistantHash_Smoke_Test()
+ {
+ var hash = new ConsistentHash();
+
+ hash.AddNode(15);
+ hash.AddNode(25);
+ hash.AddNode(172);
+
+ for (int i = 200; i < 300; i++)
+ {
+ hash.AddNode(i);
+ }
+
+ hash.RemoveNode(15);
+ hash.RemoveNode(172);
+ hash.RemoveNode(25);
+
+ var rnd = new Random();
+ for (int i = 0; i < 1000; i++)
+ {
+ Assert.AreNotEqual(15, hash.GetNode(rnd.Next().ToString()));
+ Assert.AreNotEqual(25, hash.GetNode(rnd.Next().ToString()));
+ Assert.AreNotEqual(172, hash.GetNode(rnd.Next().ToString()));
+
+ var t = hash.GetNode(rnd.Next().ToString());
+ Assert.IsTrue(t >= 200 && t < 300);
+ }
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Advanced.Algorithms.Tests/DistributedSystems/LRUCache_Tests.cs b/Advanced.Algorithms.Tests/DistributedSystems/LRUCache_Tests.cs
new file mode 100644
index 00000000..f692d7b3
--- /dev/null
+++ b/Advanced.Algorithms.Tests/DistributedSystems/LRUCache_Tests.cs
@@ -0,0 +1,30 @@
+using Advanced.Algorithms.DistributedSystems;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+
+namespace Advanced.Algorithms.Tests.DistributedSystems
+{
+ [TestClass]
+ public class LRUCache_Tests
+ {
+
+ [TestMethod]
+ public void LRUCache_Smoke_Test()
+ {
+ var cache = new LRUCache(2);
+
+ cache.Put(1, 1);
+ cache.Put(2, 2);
+ Assert.AreEqual(1, cache.Get(1));
+
+ cache.Put(3, 3);
+ Assert.AreEqual(0, cache.Get(2));
+
+ cache.Put(4, 4);
+ Assert.AreEqual(0, cache.Get(1));
+ Assert.AreEqual(3, cache.Get(3));
+ Assert.AreEqual(4, cache.Get(4));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/TravellingSalesman_Tests.cs b/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/TravellingSalesman_Tests.cs
new file mode 100644
index 00000000..0012e79f
--- /dev/null
+++ b/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/TravellingSalesman_Tests.cs
@@ -0,0 +1,43 @@
+using Advanced.Algorithms.DataStructures.Graph.AdjacencyList;
+using Advanced.Algorithms.GraphAlgorithms;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Advanced.Algorithms.Tests.GraphAlgorithms.ShortestPath
+{
+ ///
+ /// Problem details below
+ /// https://en.wikipedia.org/wiki/Travelling_salesman_problem
+ ///
+ [TestClass]
+ public class TravellingSalesman_Tests
+ {
+ [TestMethod]
+ public void TravellingSalesman_Smoke_Test()
+ {
+ var graph = new WeightedDiGraph();
+
+ graph.AddVertex(0);
+ graph.AddVertex(1);
+ graph.AddVertex(2);
+ graph.AddVertex(3);
+
+ graph.AddEdge(0, 1, 1);
+ graph.AddEdge(0, 2, 15);
+ graph.AddEdge(0, 3, 6);
+
+ graph.AddEdge(1, 0, 2);
+ graph.AddEdge(1, 2, 7);
+ graph.AddEdge(1, 3, 3);
+
+ graph.AddEdge(2, 0, 9);
+ graph.AddEdge(2, 1, 6);
+ graph.AddEdge(2, 3, 12);
+
+ graph.AddEdge(3, 0, 10);
+ graph.AddEdge(3, 1, 4);
+ graph.AddEdge(3, 2, 8);
+
+ Assert.AreEqual(21, TravellingSalesman.GetMinWeight(graph));
+ }
+ }
+}
diff --git a/Advanced.Algorithms/Combinatorics/Permutation.cs b/Advanced.Algorithms/Combinatorics/Permutation.cs
index 48626411..7bf79288 100644
--- a/Advanced.Algorithms/Combinatorics/Permutation.cs
+++ b/Advanced.Algorithms/Combinatorics/Permutation.cs
@@ -8,20 +8,20 @@ namespace Advanced.Algorithms.Combinatorics
{
public class Permutation
{
- public static List> Find(List input, bool withRepetition = false)
+ public static List> Find(List input, int r, bool withRepetition = false)
{
var result = new List>();
- Recurse(input, withRepetition, new List(), new HashSet(), result);
+ Recurse(input, r, withRepetition, new List(), new HashSet(), result);
return result;
}
- private static void Recurse(List input, bool withRepetition,
+ private static void Recurse(List input, int r, bool withRepetition,
List prefix, HashSet prefixIndices,
List> result)
{
- if (prefix.Count == input.Count)
+ if (prefix.Count == r)
{
result.Add(new List(prefix));
return;
@@ -37,53 +37,7 @@ private static void Recurse(List input, bool withRepetition,
prefix.Add(input[j]);
prefixIndices.Add(j);
- Recurse(input, withRepetition, prefix, prefixIndices, result);
-
- prefix.RemoveAt(prefix.Count - 1);
- prefixIndices.Remove(j);
- }
- }
-
- public static List> Find(List input, bool withRepetition,
- bool withInversions) where T : IComparable
- {
- var result = new List>();
-
- Recurse(input, withRepetition, withInversions,
- new List(), new HashSet(), result);
-
- return result;
- }
-
- private static void Recurse(List input,
- bool withRepetition, bool withInversions,
- List prefix, HashSet prefixIndices,
- List> result) where T : IComparable
- {
- if (prefix.Count == input.Count
- && (withInversions ||
- (prefix.Count > 0 && prefix[0].CompareTo(prefix[prefix.Count - 1]) < 0)))
- {
- result.Add(new List(prefix));
- return;
- }
-
- if (prefix.Count == input.Count)
- {
- return;
- }
-
- for (int j = 0; j < input.Count; j++)
- {
- if (prefixIndices.Contains(j) && !withRepetition)
- {
- continue;
- }
-
- prefix.Add(input[j]);
- prefixIndices.Add(j);
-
- Recurse(input, withRepetition, withInversions, prefix, prefixIndices, result);
+ Recurse(input, r, withRepetition, prefix, prefixIndices, result);
prefix.RemoveAt(prefix.Count - 1);
prefixIndices.Remove(j);
diff --git a/Advanced.Algorithms/Combinatorics/Variation.cs b/Advanced.Algorithms/Combinatorics/Variation.cs
deleted file mode 100644
index 987ad636..00000000
--- a/Advanced.Algorithms/Combinatorics/Variation.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Advanced.Algorithms.Combinatorics
-{
- public class Variation
- {
- /*Variations are arrangements of selections of objects, where the order of the selected objects matters.
- To count k-element variations of n objects, we first need to choose a k-element combination and then
- a permutation of the selected objects*/
-
- //Without repetition
- /* It is also the number of ways of putting r distinct balls into input.Count distinct boxes such that each box
- receives at most one element. */
-
- //With repetition
- /* It is the number of all ways of putting r distinct balls into input.Count distinct boxes */
- public static List> Find(List input, int r, bool withRepetition)
- {
- var result = new List>();
-
- Recurse(input, r, withRepetition, new List(), new HashSet(), result);
-
- return result;
- }
-
- private static void Recurse(List input, int r, bool withRepetition,
- List prefix, HashSet prefixIndices,
- List> result)
- {
- if (prefix.Count == r)
- {
- result.Add(new List(prefix));
- return;
- }
-
- for (int j = 0; j < input.Count; j++)
- {
- if (prefixIndices.Contains(j) && !withRepetition)
- {
- continue;
- }
-
- prefix.Add(input[j]);
- prefixIndices.Add(j);
-
- Recurse(input, r, withRepetition, prefix, prefixIndices, result);
-
- prefix.RemoveAt(prefix.Count - 1);
- prefixIndices.Remove(j);
- }
- }
- }
-}
diff --git a/Advanced.Algorithms/DataStructures/Dictionary/OpenAddressDictionary.cs b/Advanced.Algorithms/DataStructures/Dictionary/OpenAddressDictionary.cs
index 3fe70631..cd6b029d 100644
--- a/Advanced.Algorithms/DataStructures/Dictionary/OpenAddressDictionary.cs
+++ b/Advanced.Algorithms/DataStructures/Dictionary/OpenAddressDictionary.cs
@@ -37,7 +37,7 @@ public V this[K key]
//O(1) time complexity; worst case O(n)
public bool ContainsKey(K key)
{
- var hashCode = SaltHash(Math.Abs(key.GetHashCode()));
+ var hashCode = getHash(key);
var index = hashCode % bucketSize;
if (hashArray[index] == null)
@@ -84,7 +84,7 @@ public void Add(K key, V value)
Grow();
- var hashCode = SaltHash(Math.Abs(key.GetHashCode()));
+ var hashCode = getHash(key);
var index = hashCode % bucketSize;
@@ -130,7 +130,7 @@ public void Add(K key, V value)
//O(1) time complexity; worst case O(n)
public void Remove(K key)
{
- var hashCode = SaltHash(Math.Abs(key.GetHashCode()));
+ var hashCode = getHash(key);
var curIndex = hashCode % bucketSize;
if (hashArray[curIndex] == null)
@@ -228,7 +228,7 @@ public void Clear()
private void SetValue(K key, V value)
{
- var index = (SaltHash(Math.Abs(key.GetHashCode()))) % bucketSize;
+ var index = getHash(key) % bucketSize;
if (hashArray[index] == null)
{
@@ -269,7 +269,7 @@ private void SetValue(K key, V value)
private V GetValue(K key)
{
- var index = (SaltHash(Math.Abs(key.GetHashCode()))) % bucketSize;
+ var index = getHash(key) % bucketSize;
if (hashArray[index] == null)
{
@@ -363,13 +363,13 @@ private void Shrink()
}
///
- /// salt the hash with a random number
+ /// get hash
///
///
///
- private int SaltHash(int key)
+ private int getHash(K key)
{
- return key * 3;
+ return Math.Abs(key.GetHashCode());
}
//Implementation for the GetEnumerator method.
diff --git a/Advanced.Algorithms/DataStructures/HashSet/OpenAddressHashSet.cs b/Advanced.Algorithms/DataStructures/HashSet/OpenAddressHashSet.cs
index 4c6ea4bd..f3bc2170 100644
--- a/Advanced.Algorithms/DataStructures/HashSet/OpenAddressHashSet.cs
+++ b/Advanced.Algorithms/DataStructures/HashSet/OpenAddressHashSet.cs
@@ -31,7 +31,7 @@ public OpenAddressHashSet(int initialBucketSize = 2)
//O(1) time complexity; worst case O(n)
public bool Contains(V value)
{
- var hashCode = SaltHash(Math.Abs(value.GetHashCode()));
+ var hashCode = getHash(value);
var index = hashCode % bucketSize;
if (hashArray[index] == null)
@@ -78,7 +78,7 @@ public void Add(V value)
Grow();
- var hashCode = SaltHash(Math.Abs(value.GetHashCode()));
+ var hashCode = getHash(value);
var index = hashCode % bucketSize;
@@ -124,7 +124,7 @@ public void Add(V value)
//O(1) time complexity; worst case O(n)
public void Remove(V value)
{
- var hashCode = SaltHash(Math.Abs(value.GetHashCode()));
+ var hashCode = getHash(value);
var curIndex = hashCode % bucketSize;
if (hashArray[curIndex] == null)
@@ -222,7 +222,7 @@ public void Clear()
private void SetValue(V value)
{
- var index = (SaltHash(Math.Abs(value.GetHashCode()))) % bucketSize;
+ var index = getHash(value) % bucketSize;
if (hashArray[index] == null)
{
@@ -263,7 +263,7 @@ private void SetValue(V value)
private V GetValue(V value)
{
- var index = (SaltHash(Math.Abs(value.GetHashCode()))) % bucketSize;
+ var index = getHash(value) % bucketSize;
if (hashArray[index] == null)
{
@@ -357,13 +357,13 @@ private void Shrink()
}
///
- /// salt the hash with a random number
+ /// get hash
///
///
///
- private int SaltHash(int value)
+ private int getHash(V value)
{
- return value * 3;
+ return Math.Abs(value.GetHashCode());
}
//Implementation for the GetEnumerator method.
diff --git a/Advanced.Algorithms/DataStructures/Queues/CircularQueue.cs b/Advanced.Algorithms/DistributedSystems/CircularQueue.cs
similarity index 56%
rename from Advanced.Algorithms/DataStructures/Queues/CircularQueue.cs
rename to Advanced.Algorithms/DistributedSystems/CircularQueue.cs
index 513c3ffe..fdebcc63 100644
--- a/Advanced.Algorithms/DataStructures/Queues/CircularQueue.cs
+++ b/Advanced.Algorithms/DistributedSystems/CircularQueue.cs
@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace Advanced.Algorithms.DataStructures.Queues
+namespace Advanced.Algorithms.DataStructures.DistributedSystems
{
///
/// Cicular queue aka Ring Buffer using fixed size array
@@ -28,17 +26,21 @@ public CircularQueue(int size)
///
/// Note: When buffer overflows oldest data will be erased
+ /// O(1) time complexity
///
///
- public void Enqueue(T data)
+ public T Enqueue(T data)
{
+ T deleted = default(T);
+
//wrap around removing oldest element
if (end > queue.Length - 1)
{
end = 0;
- if(start == 0)
+ if (start == 0)
{
+ deleted = queue[start];
start++;
}
}
@@ -46,6 +48,7 @@ public void Enqueue(T data)
//when end meets start after wraping around
if (end == start && Count > 1)
{
+ deleted = queue[start];
start++;
}
@@ -56,9 +59,36 @@ public void Enqueue(T data)
{
Count++;
}
+
+ return deleted;
}
+ ///
+ /// O(bulk.Length) time complexity
+ ///
+ ///
+ ///
+ public IEnumerable Enqueue(T[] bulk)
+ {
+ var deletedList = new List();
+
+ foreach (var item in bulk)
+ {
+ var deleted = Enqueue(item);
+ if (!deleted.Equals(default(T)))
+ {
+ deletedList.Add(deleted);
+ }
+ }
+
+ return deletedList;
+ }
+
+ ///
+ /// O(1) time complexity
+ ///
+ ///
public T Dequeue()
{
if (Count == 0)
@@ -95,5 +125,29 @@ public T Dequeue()
return element;
}
+
+ ///
+ /// O(bulkNumber) time complexity
+ ///
+ ///
+ public IEnumerable Dequeue(int bulkNumber)
+ {
+ var deletedList = new List();
+ while (bulkNumber > 0 && Count > 0)
+ {
+ var deleted = Dequeue();
+
+ if (!deleted.Equals(default(T)))
+ {
+ deletedList.Add(deleted);
+ }
+
+ bulkNumber--;
+ }
+
+ return deletedList;
+ }
+
}
-}
+
+}
\ No newline at end of file
diff --git a/Advanced.Algorithms/DistributedSystems/ConsistentHash.cs b/Advanced.Algorithms/DistributedSystems/ConsistentHash.cs
new file mode 100644
index 00000000..95078397
--- /dev/null
+++ b/Advanced.Algorithms/DistributedSystems/ConsistentHash.cs
@@ -0,0 +1,192 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Advanced.Algorithms.DistributedSystems
+{
+
+ ///
+ /// A consistant hash implementation with MurmurHash
+ /// Adapted from https://github.com/wsq003/consistent-hash/blob/master/ConsistentHash.cs
+ ///
+ ///
+ public class ConsistentHash
+ {
+ SortedDictionary circle = new SortedDictionary();
+ int[] circleKeys;
+ int replicas;
+
+ public ConsistentHash()
+ : this(new List(), 100) { }
+
+ public ConsistentHash(IEnumerable nodes, int replicas)
+ {
+ this.replicas = replicas;
+ foreach (T node in nodes)
+ {
+ AddNode(node);
+ }
+ }
+
+ ///
+ /// Add a new bucket
+ ///
+ ///
+ public void AddNode(T node)
+ {
+ for (int i = 0; i < replicas; i++)
+ {
+ int hash = getHashCode(node.GetHashCode().ToString() + i);
+ circle[hash] = node;
+ }
+
+ circleKeys = circle.Keys.ToArray();
+ }
+
+ ///
+ /// Get the bucket for the given Key
+ ///
+ ///
+ ///
+ public T GetNode(string key)
+ {
+ int hash = getHashCode(key);
+ int first = Next_ClockWise(circleKeys, hash);
+ return circle[circleKeys[first]];
+ }
+
+ ///
+ /// Remove a bucket from lookUp
+ ///
+ ///
+ public void RemoveNode(T node)
+ {
+ for (int i = 0; i < replicas; i++)
+ {
+ int hash = getHashCode(node.GetHashCode().ToString() + i);
+ if (!circle.Remove(hash))
+ {
+ throw new Exception("Cannot remove a node that was never added.");
+ }
+ }
+
+ circleKeys = circle.Keys.ToArray();
+ }
+
+
+ ///
+ /// Move clockwise until we find a bucket with Key >= hashCode
+ ///
+ ///
+ ///
+ /// Returns the index of bucket
+ int Next_ClockWise(int[] keys, int hashCode)
+ {
+ int begin = 0;
+ int end = keys.Length - 1;
+
+ if (keys[end] < hashCode || keys[0] > hashCode)
+ {
+ return 0;
+ }
+
+ //do a binary search
+ int mid = begin;
+ while (end - begin > 1)
+ {
+ mid = (end + begin) / 2;
+ if (keys[mid] >= hashCode)
+ {
+ end = mid;
+ }
+ else
+ {
+ begin = mid;
+ }
+ }
+
+ return end;
+ }
+
+
+ private static int getHashCode(string key)
+ {
+ return (int)MurmurHash2.Hash(Encoding.Unicode.GetBytes(key));
+ }
+
+ }
+
+ internal class MurmurHash2
+ {
+ internal static UInt32 Hash(Byte[] data)
+ {
+ return Hash(data, 0xc58f1a7b);
+ }
+ const UInt32 m = 0x5bd1e995;
+ const Int32 r = 24;
+
+ [StructLayout(LayoutKind.Explicit)]
+ struct BytetoUInt32Converter
+ {
+ [FieldOffset(0)]
+ public Byte[] Bytes;
+
+ [FieldOffset(0)]
+ public UInt32[] UInts;
+ }
+
+ internal static UInt32 Hash(Byte[] data, UInt32 seed)
+ {
+ Int32 length = data.Length;
+ if (length == 0)
+ return 0;
+ UInt32 h = seed ^ (UInt32)length;
+ Int32 currentIndex = 0;
+ // array will be length of Bytes but contains Uints
+ // therefore the currentIndex will jump with +1 while length will jump with +4
+ UInt32[] hackArray = new BytetoUInt32Converter { Bytes = data }.UInts;
+ while (length >= 4)
+ {
+ UInt32 k = hackArray[currentIndex++];
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+ length -= 4;
+ }
+ currentIndex *= 4; // fix the length
+ switch (length)
+ {
+ case 3:
+ h ^= (UInt16)(data[currentIndex++] | data[currentIndex++] << 8);
+ h ^= (UInt32)data[currentIndex] << 16;
+ h *= m;
+ break;
+ case 2:
+ h ^= (UInt16)(data[currentIndex++] | data[currentIndex] << 8);
+ h *= m;
+ break;
+ case 1:
+ h ^= data[currentIndex];
+ h *= m;
+ break;
+ default:
+ break;
+ }
+
+ // Do a few final mixes of the hash to ensure the last few
+ // bytes are well-incorporated.
+
+ h ^= h >> 13;
+ h *= m;
+ h ^= h >> 15;
+
+ return h;
+ }
+ }
+}
+
diff --git a/Advanced.Algorithms/DistributedSystems/LRUCache.cs b/Advanced.Algorithms/DistributedSystems/LRUCache.cs
new file mode 100644
index 00000000..e6815e4d
--- /dev/null
+++ b/Advanced.Algorithms/DistributedSystems/LRUCache.cs
@@ -0,0 +1,67 @@
+using Advanced.Algorithms.DataStructures;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+
+namespace Advanced.Algorithms.DistributedSystems
+{
+ public class LRUCache
+ {
+ private int capacity;
+
+ private Dictionary>> lookUp
+ = new Dictionary>>();
+
+ private DoublyLinkedList> dll = new DoublyLinkedList>();
+
+ public LRUCache(int capacity)
+ {
+ if (capacity <= 0)
+ {
+ throw new Exception("Capacity must be a positive integer.");
+ }
+ this.capacity = capacity;
+ }
+
+ ///
+ /// O(1) time complexity
+ ///
+ ///
+ ///
+ public V Get(K key)
+ {
+ if (!lookUp.ContainsKey(key))
+ return default(V);
+
+ var node = lookUp[key];
+
+ //move lately used node to beginning of ddl
+ dll.Delete(node);
+ var newNode = dll.InsertFirst(node.Data);
+ lookUp[key] = newNode;
+
+ return node.Data.Item2;
+ }
+
+ ///
+ /// O(1) time complexity
+ ///
+ ///
+ ///
+ public void Put(K key, V value)
+ {
+ //evict last node of ddl if capacity overflows
+ if (lookUp.Count == capacity)
+ {
+ var nodeToEvict = dll.Last();
+ lookUp.Remove(nodeToEvict.Item1);
+ dll.DeleteLast();
+ }
+
+ //insert
+ var newNode = dll.InsertFirst(new Tuple(key, value));
+ lookUp.Add(key, newNode);
+ }
+ }
+}
diff --git a/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Bellman-Ford.cs b/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Bellman-Ford.cs
index fd65b226..aaa4b0b6 100644
--- a/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Bellman-Ford.cs
+++ b/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Bellman-Ford.cs
@@ -100,7 +100,7 @@ private ShortestPathResult tracePath(WeightedDiGraph graph,
pathStack.Push(destination);
var currentV = destination;
- while (!currentV.Equals(default(T)) && !parentMap[currentV].Equals(default(T)))
+ while (!Equals(currentV, default(T)) && !parentMap[currentV].Equals(default(T)))
{
pathStack.Push(parentMap[currentV]);
currentV = parentMap[currentV];
diff --git a/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Dijikstra.cs b/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Dijikstra.cs
index 8e03f382..b29d0736 100644
--- a/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Dijikstra.cs
+++ b/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Dijikstra.cs
@@ -178,7 +178,7 @@ private ShortestPathResult tracePath(WeightedDiGraph graph,
pathStack.Push(destination);
var currentV = destination;
- while (!currentV.Equals(default(T)) && !parentMap[currentV].Equals(default(T)))
+ while (!Equals(currentV,default(T)) && !parentMap[currentV].Equals(default(T)))
{
pathStack.Push(parentMap[currentV]);
currentV = parentMap[currentV];
diff --git a/Advanced.Algorithms/GraphAlgorithms/ShortestPath/TravellingSalesman.cs b/Advanced.Algorithms/GraphAlgorithms/ShortestPath/TravellingSalesman.cs
new file mode 100644
index 00000000..aeccace0
--- /dev/null
+++ b/Advanced.Algorithms/GraphAlgorithms/ShortestPath/TravellingSalesman.cs
@@ -0,0 +1,75 @@
+
+using Advanced.Algorithms.DataStructures.Graph.AdjacencyList;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Advanced.Algorithms.GraphAlgorithms
+{
+ ///
+ /// Problem details below
+ /// https://en.wikipedia.org/wiki/Travelling_salesman_problem
+ /// Uses dynamic programming and have
+ /// psuedo-polynomial time runtime complexity for this NP hard problem
+ ///
+ public class TravellingSalesman
+ {
+ public static int GetMinWeight(WeightedDiGraph graph)
+ {
+ return GetMinWeight(graph.ReferenceVertex, graph.ReferenceVertex,
+ graph.VerticesCount,
+ new HashSet>(),
+ new Dictionary());
+ }
+
+ public static int GetMinWeight(WeightedDiGraphVertex currentVertex,
+ WeightedDiGraphVertex tgtVertex,
+ int remainingVertexCount,
+ HashSet> visited,
+ Dictionary cache)
+ {
+ var cacheKey = $"{currentVertex.Value}-{remainingVertexCount}";
+
+ if (cache.ContainsKey(cacheKey))
+ {
+ return cache[cacheKey];
+ }
+
+ visited.Add(currentVertex);
+
+ var results = new List();
+
+ foreach (var vertex in currentVertex.OutEdges)
+ {
+ //base case
+ if (vertex.Key == tgtVertex
+ && remainingVertexCount == 1)
+ {
+ results.Add(vertex.Value);
+ break;
+ }
+
+ if (!visited.Contains(vertex.Key))
+ {
+ var result = GetMinWeight(vertex.Key, tgtVertex, remainingVertexCount - 1, visited, cache);
+
+ if (result != int.MaxValue)
+ {
+ results.Add(result + vertex.Value);
+ }
+
+ }
+ }
+
+ visited.Remove(currentVertex);
+
+ if (results.Count == 0)
+ {
+ return int.MaxValue;
+ }
+
+ var min = results.Min();
+ cache.Add(cacheKey, min);
+ return min;
+ }
+ }
+}
diff --git a/README.md b/README.md
index 7a22cd22..d4084d66 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,6 @@ Supports
### Queue
- [X] Queue (using [Dynamic Array](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DataStructures/Queues/ArrayQueue.cs) and optionally using [Doubly Linked List](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DataStructures/Queues/LinkedListQueue.cs)) ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DataStructures/Queues/Queue.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/DataStructures/Queues/Queue_Tests.cs))
-- [X] Circular Queue (Ring Buffer) ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DataStructures/Queues/CircularQueue.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/DataStructures/Queues/CircularQueue_Tests.cs))
#### Priority Queue
@@ -172,6 +171,7 @@ Note: It is observed that among the implementations here in practice, with the e
- [X] Dijikstra's algorithm ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Dijikstra.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/Dijikstras_Tests.cs)) using Fibornacci Heap.
- [X] Floyd-Warshall algorithm ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Floyd-Warshall.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/FloydWarshall_Tests.cs))
- [X] Johnson's algorithm ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/GraphAlgorithms/ShortestPath/Johnsons.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/Johnson_Tests.cs))
+- [X] Travelling Salesman Problem ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/GraphAlgorithms/ShortestPath/TravellingSalesman.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/GraphAlgorithms/ShortestPath/TravellingSalesman_Tests.cs))
### Matching
@@ -239,9 +239,14 @@ Note: On a decent desktop, in given implementations here for +ive random input i
- [X] Permutations ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/Combinatorics/Permutation.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/Combinatorics/Permutation_Tests.cs))
- [X] Combinations ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/Combinatorics/Combination.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/Combinatorics/Combination_Tests.cs))
-- [X] Variations ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/Combinatorics/Variation.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/Combinatorics/Variation_Tests.cs))
- [X] Subsets ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/Combinatorics/Subset.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/Combinatorics/Subset_Tests.cs))
+## Distributed Systems
+
+- [X] Circular Queue (Ring Buffer) ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DistributedSystems/CircularQueue.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/DistributedSystems/CircularQueue_Tests.cs))
+- [X] Consistant Hash ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DistributedSystems/ConsistantHash.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/DistributedSystems/ConsistantHash_Tests.cs))
+- [X] LRU Cache ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/DistributedSystems/LRUCache.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/DistributedSystems/LRUCache_Tests.cs))
+
## Numerical Methods
- [X] kth Smallest ([Implementation](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms/NumericalMethods/KthSmallest.cs) | [Tests](https://github.com/justcoding121/Advanced-Algorithms/tree/develop/Advanced.Algorithms.Tests/NumericalMethods/KthSmallest_Tests.cs))