Course: JavaScript

Progress (0%)

Exercise: Euclidean Distance

Exercise 35 Easy

Prerequisites for the exercise

  1. JavaScript Function Closures
  2. All previous chapters

Objective

Create a program to calculate the Euclidean distance between two points.

Description

Given two points on a Cartesian plane, the distance between them is called the Euclidean distance and is calculated by applying the very elementary Pythagoras's theorem.

So for instance, if the point ::\text{A}:: has the co-ordinates ::(x_1, y_1):: and the point ::\text{B}:: has the co-ordinates ::(x_2, y_2)::, then the distance between them is calculated by the expression below:

::\sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}::

In this exercise, you have to create a program, utilising the idea of closures, that provides a function getDistanceCalculator() which could be used to obtain a distance calculator function.

This distance calculator function takes the co-ordinates of ::\text{B}:: as two separate arguments, and meanwhile remembers the co-ordinates of ::\text{A}:: from its enclosing environment. It returns back the distance between the given points ::\text{A}:: and ::\text{B}:: as a stringified number rounded to the 1 decimal place.

In the program, we shall be able to create as many distance calculator functions as we want to, each configured with a given point ::\text{A}::.

In the end, use this program to log the distances of the points ::(30, 5)::, ::(8, 8):: and ::(-5, -10):: from the origin, and of the points ::(10, 2)::, ::(0, 1):: and ::(-90, -1):: from the point ::(5, 5)::.

Hints

Hint 1

Return a function from getDistanceCalculator().

Hint 2

The point ::\text{A}:: is provided as an argument to getDistanceCalculator() while the point ::\text{B}:: is provided as an argument to this inner returned function.

View Solution

New file

Inside the directory you created for this course on JavaScript, create a new folder called Exercise-35-Euclidean-Distance and put the .html solution files for this exercise within it.

Solution

The exercise is pretty much clear on what it requires on our side. Let's see whether you could figure it out.

We have to create a function getDistanceCalculator() that returns back another function which could then be used to calculate the distance between two given points A and B.

The point A is remembered by this inner function from its enclosing environment, and not provided to it as an argument.

This simply means that A is provided as an argument at the time of invoking getDistanceCalculator(). Let's call this parameter a.

Uptil this point, the getDistanceCalculator() function looks as follows:

function getDistanceCalculator(a) {
   return function() {
      // distance gets calculated here
   }
}

The inner function has a accessible from its enclosing environment while the point ::\text{B}:: is provided to it as an argument. Let's call this parameter b.

The distance calculating expression goes inside this inner function and is returned from it.

Simple!

Altogether we get the following code:

function getDistanceCalculator(a) {
   return function(b) {
      return (((b[0] - a[0]) ** 2 + (b[1] - a[1]) ** 2) ** 0.5).toFixed(1);
   }
}
When getDistanceCalculator() is invoked with a given value for a, an inner function is returned back from it. This returned function refers to the parameter a of its enclosing function, likewise a is kept in memory and remembered by this returned function.

Let's now use this getDistanceCalculator() function to create two distance calculating functions — one that has ::\text{A}:: configured to the origin i.e. ::(0, 0)::, and one that has ::\text{A}:: configured to the point ::(5, 5):: — and then use these to calculate the desired distances as mentioned in the description section above.

function getDistanceCalculator(a) {
   return function(b) {
      return (((b[0] - a[0]) ** 2 + (b[1] - a[1]) ** 2) ** 0.5).toFixed(1);
   }
}

var distanceFromOrigin = getDistanceCalculator([0, 0]);

console.log(distanceFromOrigin([30, 5]));
console.log(distanceFromOrigin([8, 8]));
console.log(distanceFromOrigin([-5, -10]));


var distanceFrom5_5 = getDistanceCalculator([5, 5]);

console.log(distanceFrom5_5([10, 2]));
console.log(distanceFrom5_5([0, 1]));
console.log(distanceFrom5_5([-90, -1]));
30.4 11.3 11.2 5.8 6.4 95.2

In the whole discussion above, notice the naming that we've used for each function. In a real-world program real-world program, our aim should always be to come up with extremely meaningful names for functions (and even for variables) that could clearly and quickly speak about their purpose.

distFromOrigin() quickly tells us that it is meant to return the distance of a given point from the origin. distanceFrom5_5() on the otherhand hints us that we get back the distance of a given point from the point ::(5, 5)::.

Note that in this case, it was easy for us to name this function. In some cases, it might not be possible to name the function in this way. For instance, if the point is ::(1.5, -5):: we could go like distanceFrom1.5_-5() — this is completely invalid!

"I created Codeguage to save you from falling into the same learning conundrums that I fell into."

— Bilal Adnan, Founder of Codeguage