Skip to content

Commit c3a1272

Browse files
authored
Add Manhattan distance and tests (#307)
1 parent 98dfa37 commit c3a1272

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using NUnit.Framework;
2+
using Algorithms.LinearAlgebra.Distances;
3+
using FluentAssertions;
4+
using System;
5+
6+
namespace Algorithms.Tests.LinearAlgebra.Distances
7+
{
8+
public class ManhattanTests
9+
{
10+
/// <summary>
11+
/// Test the result given by Manhattan distance function.
12+
/// </summary>
13+
/// <param name="point1">Origin point.</param>
14+
/// <param name="point2">Target point.</param>
15+
/// <param name="expectedDistance">Expected result.</param>
16+
[Test]
17+
[TestCase(new[] { 1.5 }, new[] { -1.0 }, 2.5)]
18+
[TestCase(new[] { 2.0, 3.0 }, new[] { -1.0, 5.0 }, 5)]
19+
[TestCase(new[] { 1.0, 2.0, 3.0 }, new[] { 1.0, 2.0, 3.0 }, 0)]
20+
[TestCase(new[] { 1.0, 2.0, 3.0, 4.0 }, new[] { 1.75, 2.25, -3.0, 0.5 }, 10.5)]
21+
public void DistanceTest(double[] point1, double[] point2, double expectedDistance)
22+
{
23+
Manhattan.Distance(point1, point2).Should().BeApproximately(expectedDistance, 0.01);
24+
}
25+
26+
/// <summary>
27+
/// Test that it throws ArgumentException if two different dimension arrays are given.
28+
/// </summary>
29+
/// <param name="point1">First point of N dimensions.</param>
30+
/// <param name="point2">Second point of M dimensions, M != N.</param>
31+
[Test]
32+
[TestCase(new[] { 2.0, 3.0 }, new[] { -1.0 })]
33+
[TestCase(new[] { 1.0 }, new[] { 1.0, 2.0, 3.0 })]
34+
public void DistanceThrowsArgumentExceptionOnDifferentPointDimensions(double[] point1, double[] point2)
35+
{
36+
Action action = () => Manhattan.Distance(point1, point2);
37+
action.Should().Throw<ArgumentException>();
38+
}
39+
}
40+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Algorithms.LinearAlgebra.Distances
8+
{
9+
/// <summary>
10+
/// Implementation fo Manhattan distance.
11+
/// It is the sum of the lengths of the projections of the line segment between the points onto the coordinate axes.
12+
/// In other words, it is the sum of absolute difference between the measures in all dimensions of two points.
13+
///
14+
/// Its commonly used in regression analysis.
15+
/// </summary>
16+
public static class Manhattan
17+
{
18+
/// <summary>
19+
/// Calculate Manhattan distance for two N-Dimensional points.
20+
/// </summary>
21+
/// <param name="point1">First N-Dimensional point.</param>
22+
/// <param name="point2">Second N-Dimensional point.</param>
23+
/// <returns>Calculated Manhattan distance.</returns>
24+
public static double Distance(double[] point1, double[] point2)
25+
{
26+
if (point1.Length != point2.Length)
27+
{
28+
throw new ArgumentException("Both points should have the same dimensionality");
29+
}
30+
31+
// distance = |x1-y1| + |x2-y2| + ... + |xn-yn|
32+
return point1.Zip(point2, (x1, x2) => Math.Abs(x1 - x2)).Sum();
33+
}
34+
}
35+
}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ This repository contains algorithms and data structures implemented in C# for ed
3333
* [Dynamic Programming solver](./Algorithms/Knapsack/DynamicProgrammingKnapsackSolver.cs)
3434
* [Branch and bound solver](./Algorithms/Knapsack/BranchAndBoundKnapsackSolver.cs)
3535
* [Linear Algebra](./Algorithms/LinearAlgebra)
36+
* [Distances](./Algorithms/LinearAlgebra/Distances)
37+
* [Manhattan](./Algorithms/LinearAlgebra/Distances/Manhattan.cs)
3638
* [Eigenvalue](./Algorithms/LinearAlgebra/Eigenvalue)
3739
* [Power Iteration](./Algorithms/LinearAlgebra/Eigenvalue/PowerIteration.cs)
3840
* [Numeric](./Algorithms/Numeric)

0 commit comments

Comments
 (0)