diff --git a/src/Csdsa/Algorithms/Search/Linear/LinearSSearch.IndexOf.cs b/src/Csdsa/Algorithms/Search/Linear/LinearSearch.IndexOf.cs similarity index 100% rename from src/Csdsa/Algorithms/Search/Linear/LinearSSearch.IndexOf.cs rename to src/Csdsa/Algorithms/Search/Linear/LinearSearch.IndexOf.cs diff --git a/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.FloodFill.Tests.cs b/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.FloodFill.Tests.cs new file mode 100644 index 0000000..ef9722b --- /dev/null +++ b/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.FloodFill.Tests.cs @@ -0,0 +1,46 @@ +using Csdsa.Algorithms.GraphTraversal; + +using Xunit; + +namespace Csdsa.Tests.Algorithms.GraphTraversals; + +public sealed partial class GridDfsTests +{ + [Fact] + public void FloodFill_FillsConnectedRegion() + { + int[,] grid = CreateFloodFillGrid(); + Point start = new Point(0, 0); + + GridDfs.FloodFill(grid, start, newColor: 9); + + Assert.Equal(9, grid[0, 0]); + Assert.Equal(9, grid[0, 1]); + Assert.Equal(9, grid[1, 0]); + + // Ensure other regions are unchanged. + Assert.Equal(0, grid[1, 1]); + Assert.Equal(0, grid[1, 2]); + Assert.Equal(1, grid[2, 2]); + } + + [Fact] + public void FloodFill_DoesNothing_WhenColorIsSame() + { + int[,] grid = CreateFloodFillGrid(); + Point start = new Point(0, 0); + + GridDfs.FloodFill(grid, start, newColor: 1); + + // Entire grid should be unchanged. + Assert.Equal(1, grid[0, 0]); + Assert.Equal(1, grid[0, 1]); + Assert.Equal(0, grid[0, 2]); + Assert.Equal(1, grid[1, 0]); + Assert.Equal(0, grid[1, 1]); + Assert.Equal(0, grid[1, 2]); + Assert.Equal(0, grid[2, 0]); + Assert.Equal(0, grid[2, 1]); + Assert.Equal(1, grid[2, 2]); + } +} diff --git a/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.Helpers.Tests.cs b/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.Helpers.Tests.cs new file mode 100644 index 0000000..b290db3 --- /dev/null +++ b/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.Helpers.Tests.cs @@ -0,0 +1,34 @@ +using Csdsa.Algorithms.GraphTraversal; + +namespace Csdsa.Tests.Algorithms.GraphTraversals; + +public sealed partial class GridDfsTests +{ + private static int[,] CreateSimpleIslandGrid() + { + // 1 1 0 0 + // 1 0 0 1 + // 0 0 1 1 + // 0 0 0 0 + return new[,] + { + { 1, 1, 0, 0 }, + { 1, 0, 0, 1 }, + { 0, 0, 1, 1 }, + { 0, 0, 0, 0 }, + }; + } + + private static int[,] CreateFloodFillGrid() + { + // 1 1 0 + // 1 0 0 + // 0 0 1 + return new[,] + { + { 1, 1, 0 }, + { 1, 0, 0 }, + { 0, 0, 1 }, + }; + } +} diff --git a/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.NumberOfIslandsDfs.Tests.cs b/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.NumberOfIslandsDfs.Tests.cs new file mode 100644 index 0000000..d060695 --- /dev/null +++ b/tests/Csdsa.Tests/Algorithms/GraphTraversals/GridDfs.NumberOfIslandsDfs.Tests.cs @@ -0,0 +1,32 @@ +using Csdsa.Algorithms.GraphTraversal; + +using Xunit; + +namespace Csdsa.Tests.Algorithms.GraphTraversals; + +public sealed partial class GridDfsTests +{ + [Fact] + public void NumberOfIslandsDfs_CountsCorrectIslands() + { + int[,] grid = CreateSimpleIslandGrid(); + + int count = GridDfs.NumberOfIslandsDFS(grid); + + Assert.Equal(2, count); + } + + [Fact] + public void NumberOfIslandsDfs_ReturnsZero_WhenNoIslands() + { + int[,] grid = + { + { 0, 0, 0 }, + { 0, 0, 0 }, + }; + + int count = GridDfs.NumberOfIslandsDFS(grid); + + Assert.Equal(0, count); + } +} diff --git a/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Helpers.Tests.cs b/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Helpers.Tests.cs new file mode 100644 index 0000000..53d01d4 --- /dev/null +++ b/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Helpers.Tests.cs @@ -0,0 +1,32 @@ +using Csdsa.Algorithms.GraphTraversal; + +namespace Csdsa.Tests.Algorithms.GraphTraversals; + +public sealed partial class TreeDfsTests +{ + // Builds a simple binary tree: + // 1 + // / \ + // 2 3 + // / \ + // 4 5 + private static TreeNode CreateSampleTree() + { + return new TreeNode + { + Val = 1, + Left = new TreeNode + { + Val = 2, + Left = new TreeNode { Val = 4 }, + Right = new TreeNode { Val = 5 }, + }, + Right = new TreeNode + { + Val = 3, + Left = new TreeNode { Val = 6 }, + Right = new TreeNode { Val = 7 }, + }, + }; + } +} diff --git a/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Postorder.Tests.cs b/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Postorder.Tests.cs new file mode 100644 index 0000000..2ae3257 --- /dev/null +++ b/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Postorder.Tests.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +using Csdsa.Algorithms.GraphTraversal; + +using Xunit; + +namespace Csdsa.Tests.Algorithms.GraphTraversals; + +public sealed partial class TreeDfsTests +{ + [Fact] + public void Postorder_ReturnsLeftRightRootOrder() + { + TreeNode root = CreateSampleTree(); + + IReadOnlyList traversal = TreeDfs.Postorder(root); + + // Expected postorder: 4,5,2,6,7,3,1 + Assert.Equal(new[] { 4, 5, 2, 6, 7, 3, 1 }, traversal); + } + + [Fact] + public void Postorder_OnNullRoot_ReturnsEmpty() + { + IReadOnlyList traversal = TreeDfs.Postorder(root: null); + + Assert.Empty(traversal); + } +} diff --git a/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Preorder.Tests.cs b/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Preorder.Tests.cs new file mode 100644 index 0000000..8b6346a --- /dev/null +++ b/tests/Csdsa.Tests/Algorithms/GraphTraversals/TreeDfs.Preorder.Tests.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +using Csdsa.Algorithms.GraphTraversal; + +using Xunit; + +namespace Csdsa.Tests.Algorithms.GraphTraversals; + +public sealed partial class TreeDfsTests +{ + [Fact] + public void Preorder_ReturnsRootLeftRightOrder() + { + TreeNode root = CreateSampleTree(); + + IReadOnlyList traversal = TreeDfs.Preorder(root); + + // Expected preorder: 1,2,4,5,3,6,7 + Assert.Equal(new[] { 1, 2, 4, 5, 3, 6, 7 }, traversal); + } + + [Fact] + public void Preorder_OnNullRoot_ReturnsEmpty() + { + IReadOnlyList traversal = TreeDfs.Preorder(root: null); + + Assert.Empty(traversal); + } +} diff --git a/tests/Csdsa.Tests/Algorithms/Search/Linear/LinearSSearch.RemoveAllMatches.Tests.cs b/tests/Csdsa.Tests/Algorithms/Search/Linear/LinearSearch.RemoveAllMatches.Tests.cs similarity index 100% rename from tests/Csdsa.Tests/Algorithms/Search/Linear/LinearSSearch.RemoveAllMatches.Tests.cs rename to tests/Csdsa.Tests/Algorithms/Search/Linear/LinearSearch.RemoveAllMatches.Tests.cs diff --git a/tests/Csdsa.Tests/DataStructures/Traversals/SequentialTraversal.TravereseWithIndex.Tests.cs b/tests/Csdsa.Tests/DataStructures/Traversals/SequentialTraversal.TraverseWithIndex.Tests.cs similarity index 100% rename from tests/Csdsa.Tests/DataStructures/Traversals/SequentialTraversal.TravereseWithIndex.Tests.cs rename to tests/Csdsa.Tests/DataStructures/Traversals/SequentialTraversal.TraverseWithIndex.Tests.cs diff --git a/tests/Csdsa.Tests/DataStructures/Vectors/Vector.AsSSpan.Tests.cs b/tests/Csdsa.Tests/DataStructures/Vectors/Vector.AsSSpan.Tests.cs deleted file mode 100644 index 474f4d0..0000000 --- a/tests/Csdsa.Tests/DataStructures/Vectors/Vector.AsSSpan.Tests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Csdsa.DataStructures.Vectors; -using Xunit; - -namespace Csdsa.Tests.DataStructures.Vectors; - -public class VectorAsSpanTests -{ - private const double Tolerance = 1e-6; - - [Fact] - public void AsSpan_ReturnsCorrectView() - { - double[] components = { 1, 2, 3 }; - Vector vector = new Vector(components); - - var span = vector.AsSpan(); - - Assert.Equal(components.Length, span.Length); - - for (int i = 0; i < components.Length; i++) - { - Assert.Equal(components[i], span[i], Tolerance); - } - } -} diff --git a/tests/Csdsa.Tests/DataStructures/Vectors/Vector.AsSpan.Tests.cs b/tests/Csdsa.Tests/DataStructures/Vectors/Vector.AsSpan.Tests.cs new file mode 100644 index 0000000..168658f --- /dev/null +++ b/tests/Csdsa.Tests/DataStructures/Vectors/Vector.AsSpan.Tests.cs @@ -0,0 +1,51 @@ +using Csdsa.DataStructures.Vectors; +using Xunit; + +namespace Csdsa.Tests.DataStructures.Vectors; + +public class VectorAsSpanTests +{ + private const double Tolerance = 1e-6; + + [Fact] + public void AsSpan_ReturnsCorrectView() + { + double[] components = { 1, 2, 3 }; + Vector vector = new Vector(components); + + var span = vector.AsSpan(); + + Assert.Equal(components.Length, span.Length); + + for (int i = 0; i < components.Length; i++) + { + Assert.Equal(components[i], span[i], Tolerance); + } + } + + [Fact] + public void AsSpan_ContainsSameComponents() + { + Vector vector = new Vector(new[] { 1, 2, 3 }); + + Span span = vector.AsSpan(); + + Assert.Equal(3, span.Length); + Assert.Equal(1, span[0]); + Assert.Equal(2, span[1]); + Assert.Equal(3, span[2]); + } + + [Fact] + public void AsSpan_ReturnsIndependentCopy() + { + Vector vector = new Vector(new[] { 1, 2, 3 }); + + Span span = vector.AsSpan(); + span[0] = 99; + + // Since AsSpan returns a span over a copy, original vector should be unchanged. + Span span2 = vector.AsSpan(); + Assert.Equal(1, span2[0]); + } +}