Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimum distance between two elements in a circular array

Given a circular array, what is an efficient way to determine the minimum distance between two elements?

For example moving from here

[0,0,0,0,0,1]

To here

[1,0,0,0,0,0]

Is more convenient from the outer bounds, whilst moving from here

[0,0,0,0,0,1]

to here

[0,0,0,1,0,0]

is more convenient internally.

My initial idea was this:

sourceLocation = rotatorElements["pos"].indexOf(1);
targetLocation = rotatorElements["pos"].rotate(delta).indexOf(1);

var D = Math.abs(targetLocation - sourceLocation);
var O = Math.abs(rotatorElements["pos"].length - D);

if ((D - O == 0)) direction = 1;
else {
    if (D < O) direction = -1;
    else direction = 1;
}

Note: rotate rotates the circular array by a defined number of positions.

like image 415
grumpyGAMER Avatar asked May 03 '13 15:05

grumpyGAMER


Video Answer


2 Answers

Calculating the absolute distance between the elements is useful:

var dist = Math.abs(targetLocation - sourceLocation);

Then you can just check if it's more or less than half the length of the array. If the distance is more than half the length, it's closer to wrap around:

if (dist < rotatorElements["pos"].length / 2) {
  // move internally
} else {
  // wrap around
}

Edit:

I pasted the code together:

function move(sourceLocation, targetLocation, length) {
    var dist = Math.abs(targetLocation - sourceLocation);
    var direction = sourceLocation < targetLocation ? 1 : -1;
    if (dist < length / 2) {
        console.log('internally, direction =', direction);
    } else {
        console.log('wrap, direction =', -direction);
    }
}

move(5, 0, 6);
move(5, 3, 6);

Output:

wrap, direction = 1
internally, direction = -1

Demo: http://jsfiddle.net/bUCmk/

like image 116
Guffa Avatar answered Oct 30 '22 13:10

Guffa


Edit: I think I answered the question in the title, but what you want is a direction not a distance. Then:

function getDirection(from, to, array) {
    if (from === to) {
        return 0;
    }
    var internal = (Math.max(from, to) - Math.min(from, to) < array.length/2) ? true : false;
    if (internal && from < to
       ||
       !internal && from > to
    ) {
       return 1;
    } else {
       return -1;
    }
}
like image 44
peterfoldi Avatar answered Oct 30 '22 14:10

peterfoldi