Reputation: 969
I want to compute the distance between numbers with help of the system described in the attached image.
For example: distance between 7 and 5 is -2, distance between 7 and 1 is 2 etc...
Any ideas how to do this in c++? The prefered direction is counter clockwise... I am using a (int) vector.
Upvotes: 0
Views: 2118
Reputation: 213258
These are really complicated answers. Here is a simpler one:
int distance(int x, int y) {
int d = (y - x) & 7;
return d > 4 ? d - 8 : d;
}
This always returns a result in the range -3..+4. Modular arithmetic is a little simpler to write when the ring size is a power of two, as is the case here.
distance(7, 5) = -2
distance(5, 7) = +2
distance(6, 2) = +4
distance(2, 6) = +4
We use & 7
because it is the simplest way to get the modulo. Alternatively, you can use % 8
, but you must also add 8 in order to make sure that the input is not negative:
int d = (y - x + 8) % 8; // same result
Alternatively, you can handle negative numbers explicitly:
int d = (y - x) % 8;
if (d < 0) {
d += 8;
}
// same result
This is just a matter of style.
Upvotes: 5
Reputation: 320371
If you do it in straightforward way (by considering all possibilities) it might look as follows
int distance(int a, int b)
{ // Distance from `a` to `b`
int d = b - a;
return
a <= b ?
(d <= +4 ? d : d - 8) :
(d <= -4 ? d + 8 : d);
}
which, if you prefer, can be rewritten as
int distance(int a, int b)
{ // Distance from `a` to `b`
int d = b - a;
return -4 < d && d <= 4 ? d : (d > 0 ? d - 8 : d + 8);
}
An alternative, more elegant approach would be to always calculate the positive CCW distance and flip it to negative CW distance if it is greater than 4
int distance(int a, int b)
{ // Distance from `a` to `b`
int d = (b + 8 - a) % 8;
// `d` is CCW distance from `a` to `b`
return d <= 4 ? d : d - 8;
}
But if you want the compiler to generate the most efficient code for this, follow the golden rule "use unsigned types everywhere you can, use signed types only if you have to":
int distance(unsigned a, unsigned b)
{ // Distance from `a` to `b`
unsigned d = (b + 8 - a) % 8;
// `d` is CCW distance from `a` to `b`
return d <= 4 ? d : (int) d - 8;
}
Upvotes: 2
Reputation: 3305
The following code is prepared to meet all of your needs, for example I assume, that if direction is clockwise the distance is to be negative.
#include <iostream>
#define RING_SIZE 8
enum direction
{
clockwise,
counterClockwise
};
int distance(int a, int b, direction dir)
{
int dist;
if(dir == clockwise)
{
if(a>b)
{
dist = -(a-b);
}
else
{
dist =-(RING_SIZE-b+a);
}
}
else
{
if(a<b)
{
dist = b-a;
}
else
{
dist = RING_SIZE-a+b;
}
}
if(a==b) dist = 0;//Add this if distance between same point must to be 0
return dist;
}
int main()
{
std::cout << distance(7, 2, clockwise) << std::endl;
}
Upvotes: 1
Reputation: 340
I am pretty sure this works:
list = [0,1,2,3,4,5,6,7]
distance(x,y) {
a = y-x
b = length(list)-abs(y-x)
z = min(abs(a), abs(b))
if(z=abs(a)) { return a }
if(z=abs(b)) { return b }
}
where abs()
is the mathematical absolute value function.
I make a few assumptions here.
As @Hédi Ghédiri pointed out, you are not counting counter-clockwise both times. I am assuming you count the shortest path to the number. (I used the mathematical min()
function)
You prefer the positive value over the negative value (@Harper's comment). If you prefer the negative value, switch the last two if
statements.
There may be a more concise method, but this (hopefully) works. Please comment if it is wrong. Hope this is helpful!
Edit: this is psuedocode. It should be easy to write in c++. Use the abs()
function in <stdlib.h>
Forget about list
and length(list)
. Use int
types for the variables, and everything else should work.
Upvotes: 1
Reputation: 4632
For simplicity you can find the element from std::find and get the distance from start from std::distance
for example as you mentioned the data saved in int vector
std::vector<int>::iterator it1 = std::find(myvec.begin(), myvec.end(), val_1);
std::vector<int>::iterator it2 = std::find(myvec.begin(), myvec.end(), val_2);
int dist = std::distance(myvec.begin(),it1) - std::distance(myvec.begin.it2);
if(dist < 0) return dist
else(dist > 0) return myvector.size() - dist()
So hope this will give the distance as the image ...
Upvotes: 1
Reputation: 2233
I think this should work
int func(a,b)
{
dist=(b-a);
if(dist<0)
dist +=8;
return dist;
}
in case you're really stuck
Upvotes: 0