Engo
Engo

Reputation: 969

How to compute distance between numbers in c++?

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.

enter image description here

Upvotes: 0

Views: 2118

Answers (6)

Dietrich Epp
Dietrich Epp

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

AnT stands with Russia
AnT stands with Russia

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

Rama
Rama

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

Timothy Higinbottom
Timothy Higinbottom

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.

  1. 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)

  2. 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

Wickkiey
Wickkiey

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

Dinaiz
Dinaiz

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

Related Questions