I got your initial approach, but I couldn't understand your execution... There are a few things I might add to it and few thing I might remove. My style of writing code always goes after readability first and optimization second. If I can achieve both then that's a bonus...
Your approach my way
Actually I had the same idea as soon as I read your problem statement but well you executed it first so its no longer my idea.
Here is how I interpreted your approach...
The number scale
1-2-3-4-5-6-7-8
Lets choose two variables, in which one will act as a starting node and one will act as the ending node (In other words from and to). I am going with your pick, from = 2 => f
and to = 5 => t
1-2-3-4-5-6-7-8
| |
f t
Now to find the distance I need to find the absolute difference between from
and to
1-2-3-4-5-6-7-8
| |
f~~3~~t
Okay, now I have my absolute difference... This means I need to travel three nodes from 2 to reach 5, but I can also travel the other way around. Therefore I will call my absolute difference as forwards
To travel the other way around, I need to know two offsets. One is from the start of my number scale to my from
and other is from the end of my number scale to my to
1-2-3-4-5-6-7-8
| |
< 1 3 >
Okay... I now have my 2 offsets I will name them leftOffset => 1
and rightOffset => 3
To get the reverse distance,(I shall call it backwards
) I need to add my two offsets and one for link between end and start. Therefore backwards = leftOffset + rightOffset + 1 => 5
Okay now that everything is set, I need to find the minimum distance. In this case it will be the forwards
variable... But the values of my from
and to
can vary. So, what if their values are reversed from = 5, to = 2
In this case the variables forwards
and backwards
exchange their meaning. Therefore I need to react the same way and check if my calculations are correct. To do this I will just negate the final result, if my from
is greater than to
Here is my version of your code (I also made it so that you can change your number series, using the min value):
function findClosest(from, to, min, max){
let smaller = (from > to) ? to : from,
bigger = (from < to) ? to : from;
let leftOffset = smaller - min,
rightOffset = max - bigger;
let forwards = bigger - smaller,
backwards = leftOffset + rightOffset + 1;
let result = (backwards > forwards) ? forwards : -backwards;
result = (from > to) ? -result: result;
return result
}
console.log("Input: (from, to, min, max), Output: (minimum distance)");
// ---- Your Test Cases ---- //
console.log("Input: (2, 5, 1, 8), Output: " + findClosest(2, 5, 1, 8)); // 3
console.log("Input: (1, 8, 1, 8), Output: " + findClosest(1, 8, 1, 8)); // -1
console.log("Input: (8, 1, 1, 8), Output: " + findClosest(8, 1, 1, 8)); // 1
console.log("Input: (7, 1, 1, 8), Output: " + findClosest(7, 1, 1, 8)); // 2
console.log("Input: (8, 5, 1, 8), Output: " + findClosest(8, 5, 1, 8)); // -3
// -- My custom test case -- //
console.log("Input: (2, 5, 2, 5), Output: " + findClosest(2, 5, 2, 5)); // -1
Now for my next approach
Everything you have seen above remains the same, but now I don't calculate the offsets. Instead I calculate the total number of elements.
Since I have my forwards
variable set to my absolute difference... It is actually the length of my line segment from 2 to 5 on my number scale.
Then I can just subtract this segment from number scale to get the reverse distance
1-2-3-4-5-6-7-8
| |
|~~3~~|
|~seg~|
1-2-3-4-5-6-7-8
|~~~~~~8~~~~~~|
|~ num-scale ~|
seg - num-scale
|~|~ 5 ~|~~~~~|
Everything else remains the same...
Hence here is the code (Yes, I also made this code to be series extensible):
function findClosestTwo(from, to, min, max){
let smaller = (from > to) ? to : from,
bigger = (from < to) ? to : from;
let totalNumberOfElements = max - min + 1;
let forwards = bigger - smaller,
backwards = totalNumberOfElements - forwards;
let result = (forwards < backwards) ? forwards : -backwards;
result = (from > to) ? -result : result;
return result;
}
console.log("Input: (from, to, min, max), Output: (minimum distance)");
// ---- Your Test Cases ---- //
console.log("Input: (2, 5, 1, 8), Output: " + findClosestTwo(2, 5, 1, 8)); // 3
console.log("Input: (1, 8, 1, 8), Output: " + findClosestTwo(1, 8, 1, 8)); // -1
console.log("Input: (8, 1, 1, 8), Output: " + findClosestTwo(8, 1, 1, 8)); // 1
console.log("Input: (7, 1, 1, 8), Output: " + findClosestTwo(7, 1, 1, 8)); // 2
console.log("Input: (8, 5, 1, 8), Output: " + findClosestTwo(8, 5, 1, 8)); // -3
// -- My custom test case -- //
console.log("Input: (2, 5, 2, 5), Output: " + findClosestTwo(2, 5, 2, 5)); // -1
If you are crazy about the optimizations, you can technically compress both the functions in a single line.
Note: I have not used any in-built math functions in JavaScript for performance of course.
Note: These functions should in theory be very convenient for you to use as you never have to deviate and change the min and max values.
Note: You can also increase your number scale to include negative values.
Edit: I just now got the previous answer to your question... His approach is kind of like my second function but different in theory. I did not even read his answer because the names and comments made me dizzy. Its a cool approach though, nice one fam.