From a7d7daf8552c7dbb19b7aeb7ee735ef53e63b7e3 Mon Sep 17 00:00:00 2001 From: Paulo Date: Mon, 14 Oct 2024 19:03:26 -0300 Subject: [PATCH] feat(math): implement euclidean distance --- DIRECTORY.md | 1 + maths/euclidean_distance.ts | 25 ++++++++++++++++ maths/test/euclidean_distance.test.ts | 43 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 maths/euclidean_distance.ts create mode 100644 maths/test/euclidean_distance.test.ts diff --git a/DIRECTORY.md b/DIRECTORY.md index 185bae95..85c95c3e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -109,6 +109,7 @@ * [Degrees To Radians](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/degrees_to_radians.ts) * [Digit Sum](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/digit_sum.ts) * [Double Factorial Iterative](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/double_factorial_iterative.ts) + * [Euclidean Distance](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/euclidean_distance.ts) * [Euler Totient](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/euler_totient.ts) * [Factorial](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/factorial.ts) * [Factors](https://github.com/TheAlgorithms/TypeScript/blob/HEAD/maths/factors.ts) diff --git a/maths/euclidean_distance.ts b/maths/euclidean_distance.ts new file mode 100644 index 00000000..cbace917 --- /dev/null +++ b/maths/euclidean_distance.ts @@ -0,0 +1,25 @@ +/** + * @description Calculate the Euclidean distance between two vectors. + * @param {number[]} vectorA - The first vector. + * @param {number[]} vectorB - The second vector. + * @return {number} - The Euclidean distance between the two vectors. + * @throws Will throw an error if the vectors do not have the same dimensions. + * @see https://en.wikipedia.org/wiki/Euclidean_distance + * @example euclideanDistance([0, 0], [3, 4]) = 5 + * @example euclideanDistance([1, 2, 3], [4, 5, 6]) = 5.196 + */ +export const euclideanDistance = ( + vectorA: number[], + vectorB: number[] +): number => { + if (vectorA.length !== vectorB.length) { + throw new Error('Vectors must have the same dimensions') + } + + let sum: number = 0 + for (let index: number = 0; index < vectorA.length; index++) { + sum += (vectorA[index] - vectorB[index]) ** 2 + } + + return Math.sqrt(sum) +} diff --git a/maths/test/euclidean_distance.test.ts b/maths/test/euclidean_distance.test.ts new file mode 100644 index 00000000..6e8158da --- /dev/null +++ b/maths/test/euclidean_distance.test.ts @@ -0,0 +1,43 @@ +import { euclideanDistance } from '../euclidean_distance' + +describe('Euclidean distance', () => { + test.each([ + [[0, 0], [0, 0], 0], + [[1, 0], [0, 0], 1], + [[0, 1], [0, 0], 1], + [[3, 4], [0, 0], 5], + [[1, 2, 3], [4, 5, 6], 5.196152422706632], + [[-1, -1], [1, 1], Math.sqrt(8)], + [[2, 3], [2, 3], 0] + ])('between %p and %p should be %f', (point1, point2, expected) => { + expect(euclideanDistance(point1, point2)).toBeCloseTo(expected) + }) + + test.each([ + [[0, 0], [0]], + [[1], [1, 2]], + [ + [1, 2, 3], + [4, 5] + ] + ])( + 'should throw an error for mismatched dimensions %p and %p', + (point1, point2) => { + expect(() => euclideanDistance(point1, point2)).toThrowError( + 'Vectors must have the same dimensions' + ) + } + ) + + test('should handle empty vectors', () => { + expect(euclideanDistance([], [])).toBe(0) + }) + + test('should handle large vectors', () => { + const largeVector1 = Array(1000).fill(1) + const largeVector2 = Array(1000).fill(2) + expect(euclideanDistance(largeVector1, largeVector2)).toBeCloseTo( + Math.sqrt(1000) + ) + }) +})