diff --git a/Algorithms.Tests/Algorithms.Tests.csproj b/Algorithms.Tests/Algorithms.Tests.csproj
index 893564d8..d6d63755 100644
--- a/Algorithms.Tests/Algorithms.Tests.csproj
+++ b/Algorithms.Tests/Algorithms.Tests.csproj
@@ -20,6 +20,7 @@
+
diff --git a/Algorithms.Tests/RecommenderSystem/CollaborativeFilteringTests.cs b/Algorithms.Tests/RecommenderSystem/CollaborativeFilteringTests.cs
new file mode 100644
index 00000000..208de6fb
--- /dev/null
+++ b/Algorithms.Tests/RecommenderSystem/CollaborativeFilteringTests.cs
@@ -0,0 +1,95 @@
+using Algorithms.RecommenderSystem;
+using Moq;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace Algorithms.Tests.RecommenderSystem
+{
+ [TestFixture]
+ public class CollaborativeFilteringTests
+ {
+ private Mock? mockSimilarityCalculator;
+ private CollaborativeFiltering? recommender;
+ private Dictionary> testRatings = null!;
+
+ [SetUp]
+ public void Setup()
+ {
+ mockSimilarityCalculator = new Mock();
+ recommender = new CollaborativeFiltering(mockSimilarityCalculator.Object);
+
+ testRatings = new Dictionary>
+ {
+ ["user1"] = new()
+ {
+ ["item1"] = 5.0,
+ ["item2"] = 3.0,
+ ["item3"] = 4.0
+ },
+ ["user2"] = new()
+ {
+ ["item1"] = 4.0,
+ ["item2"] = 2.0,
+ ["item3"] = 5.0
+ },
+ ["user3"] = new()
+ {
+ ["item1"] = 3.0,
+ ["item2"] = 4.0,
+ ["item4"] = 3.0
+ }
+ };
+ }
+
+ [Test]
+ [TestCase("item1", 4.0, 5.0)]
+ [TestCase("item2", 2.0, 4.0)]
+ public void CalculateSimilarity_WithValidInputs_ReturnsExpectedResults(
+ string commonItem,
+ double rating1,
+ double rating2)
+ {
+ var user1Ratings = new Dictionary { [commonItem] = rating1 };
+ var user2Ratings = new Dictionary { [commonItem] = rating2 };
+
+ var similarity = recommender?.CalculateSimilarity(user1Ratings, user2Ratings);
+
+ Assert.That(similarity, Is.InRange(-1.0, 1.0));
+ }
+
+ [Test]
+ public void CalculateSimilarity_WithNoCommonItems_ReturnsZero()
+ {
+ var user1Ratings = new Dictionary { ["item1"] = 5.0 };
+ var user2Ratings = new Dictionary { ["item2"] = 4.0 };
+
+ var similarity = recommender?.CalculateSimilarity(user1Ratings, user2Ratings);
+
+ Assert.That(similarity, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void PredictRating_WithNonexistentItem_ReturnsZero()
+ {
+ var predictedRating = recommender?.PredictRating("nonexistentItem", "user1", testRatings);
+
+ Assert.That(predictedRating, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void PredictRating_WithOtherUserHavingRatedTargetItem_ShouldCalculateSimilarityAndWeightedSum()
+ {
+ var targetItem = "item1";
+ var targetUser = "user1";
+
+ mockSimilarityCalculator?
+ .Setup(s => s.CalculateSimilarity(It.IsAny>(), It.IsAny>()))
+ .Returns(0.8);
+
+ var predictedRating = recommender?.PredictRating(targetItem, targetUser, testRatings);
+
+ Assert.That(predictedRating, Is.Not.EqualTo(0.0d));
+ Assert.That(predictedRating, Is.EqualTo(3.5d).Within(0.01));
+ }
+ }
+}
diff --git a/Algorithms/RecommenderSystem/CollaborativeFiltering.cs b/Algorithms/RecommenderSystem/CollaborativeFiltering.cs
new file mode 100644
index 00000000..8da58b8a
--- /dev/null
+++ b/Algorithms/RecommenderSystem/CollaborativeFiltering.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Algorithms.RecommenderSystem
+{
+ public class CollaborativeFiltering
+ {
+ private readonly ISimilarityCalculator similarityCalculator;
+
+ public CollaborativeFiltering(ISimilarityCalculator similarityCalculator)
+ {
+ this.similarityCalculator = similarityCalculator;
+ }
+
+ ///
+ /// Method to calculate similarity between two users using Pearson correlation.
+ ///
+ /// Rating of User 1.
+ /// Rating of User 2.
+ /// double value to reflect the index of similarity between two users.
+ public double CalculateSimilarity(Dictionary user1Ratings, Dictionary user2Ratings)
+ {
+ var commonItems = user1Ratings.Keys.Intersect(user2Ratings.Keys).ToList();
+ if (commonItems.Count == 0)
+ {
+ return 0;
+ }
+
+ var user1Scores = commonItems.Select(item => user1Ratings[item]).ToArray();
+ var user2Scores = commonItems.Select(item => user2Ratings[item]).ToArray();
+
+ var avgUser1 = user1Scores.Average();
+ var avgUser2 = user2Scores.Average();
+
+ double numerator = 0;
+ double sumSquare1 = 0;
+ double sumSquare2 = 0;
+ double epsilon = 1e-10;
+
+ for (var i = 0; i < commonItems.Count; i++)
+ {
+ var diff1 = user1Scores[i] - avgUser1;
+ var diff2 = user2Scores[i] - avgUser2;
+
+ numerator += diff1 * diff2;
+ sumSquare1 += diff1 * diff1;
+ sumSquare2 += diff2 * diff2;
+ }
+
+ var denominator = Math.Sqrt(sumSquare1 * sumSquare2);
+ return Math.Abs(denominator) < epsilon ? 0 : numerator / denominator;
+ }
+
+ ///
+ /// Predict a rating for a specific item by a target user.
+ ///
+ /// The item for which the rating needs to be predicted.
+ /// The user for whom the rating is being predicted.
+ ///
+ /// A dictionary containing user ratings where:
+ /// - The key is the user's identifier (string).
+ /// - The value is another dictionary where the key is the item identifier (string), and the value is the rating given by the user (double).
+ ///
+ /// The predicted rating for the target item by the target user.
+ /// If there is insufficient data to predict a rating, the method returns 0.
+ ///
+ public double PredictRating(string targetItem, string targetUser, Dictionary> ratings)
+ {
+ var targetUserRatings = ratings[targetUser];
+ double totalSimilarity = 0;
+ double weightedSum = 0;
+ double epsilon = 1e-10;
+
+ foreach (var otherUser in ratings.Keys.Where(u => u != targetUser))
+ {
+ var otherUserRatings = ratings[otherUser];
+ if (otherUserRatings.ContainsKey(targetItem))
+ {
+ var similarity = similarityCalculator.CalculateSimilarity(targetUserRatings, otherUserRatings);
+ totalSimilarity += Math.Abs(similarity);
+ weightedSum += similarity * otherUserRatings[targetItem];
+ }
+ }
+
+ return Math.Abs(totalSimilarity) < epsilon ? 0 : weightedSum / totalSimilarity;
+ }
+ }
+}
diff --git a/Algorithms/RecommenderSystem/ISimilarityCalculator.cs b/Algorithms/RecommenderSystem/ISimilarityCalculator.cs
new file mode 100644
index 00000000..e055a3c7
--- /dev/null
+++ b/Algorithms/RecommenderSystem/ISimilarityCalculator.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Algorithms.RecommenderSystem
+{
+ public interface ISimilarityCalculator
+ {
+ double CalculateSimilarity(Dictionary user1Ratings, Dictionary user2Ratings);
+ }
+}
diff --git a/README.md b/README.md
index 93e048d2..f67c4356 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,8 @@ find more than one implementation for the same objective but using different alg
* [Josephus Problem](./Algorithms/Numeric/JosephusProblem.cs)
* [Newton's Square Root Calculation](./Algorithms/NewtonSquareRoot.cs)
* [SoftMax Function](./Algorithms/Numeric/SoftMax.cs)
+ * [RecommenderSystem](./Algorithms/RecommenderSystem)
+ * [CollaborativeFiltering](./Algorithms/RecommenderSystem/CollaborativeFiltering)
* [Searches](./Algorithms/Search)
* [A-Star](./Algorithms/Search/AStar/)
* [Binary Search](./Algorithms/Search/BinarySearcher.cs)