Reputation: 4148
I have an array and three indexes:
var arr = ['a', 'b', 'c', 'd'];
var f = 0; // first element
var l = arr.length - 1; // last element
var c = 0; // current element
I'm trying to write a function that makes the index c
to cycle through the array. The requirement is for it to never reach the index l
. So, whenever c
reaches a certain value, f
and l
need to be increased as well.
A reasonable value to work as a limit for c I thought would be the middle point between f and l. The function I wrote is this:
var mod = function(x, m) {
var r = x%m;
return r<0 ? r+m : r;
}
while (true) {
console.log('f', f, 'l', l, 'c', c);
if (c == l) {
console.log('error');
}
c = mod(c + 1, arr.length);
if (c > mod(l - f, arr.length) / 2) {
f = mod(f + 1, arr.length);
l = mod(l + 1, arr.length);
}
}
It doesn't work, clearly. Is there a nice simple formula to with the modulo operator to get what I want or the approach is totally wrong?
Here's a fiddle to try it: https://jsfiddle.net/wku37h9e/2/
Edit:
Explaining the purpose of this would be a bit long. Let's just say that in the array are stored the positions of external elements which I have to constantly move around. When the c
is close to the l
, I advance all the indexes. Graphically would be like this:
1. [f|c] [ ] [ ] [ l ]
2. [ f ] [ c ] [ ] [ l ]
3. [ l ] [ f ] [ c ] [ ] // here I start moving things around
4. [ ] [ l ] [ f ] [ c ]
5. [ c ] [ ] [ l ] [ f ]
6. [ f ] [ c ] [ ] [ l ]
And so on. With more elements in the array there would be more distance between the indexes.
I also use a different than normal version of mod to take in account negative numbers.
I hope it's a bit clearer now
Upvotes: 0
Views: 1775
Reputation: 386568
I calculate only l
with the half of the array length plus c
. f
is then the next index. All numbers are positve.
c f l 1. [ c ] [ ] [ l ] [ f ] 0 3 2 l = length / 2 + c, f = l + 1 both mod length 2. [ f ] [ c ] [ ] [ l ] 1 0 3 3. [ l ] [ f ] [ c ] [ ] 2 1 0 4. [ ] [ l ] [ f ] [ c ] 3 2 1 5. [ c ] [ ] [ l ] [ f ] 0 3 2 6. [ f ] [ c ] [ ] [ l ] 1 0 3
var arr = ['a', 'b', 'c', 'd'],
c, f, l;
for (c = 0; c < arr.length; c++) {
l = (arr.length / 2 + c) % arr.length;
f = (l + 1) % arr.length;
document.write('c:' + c + ' f: ' + f + ' l: ' + l + '<br>');
}
Upvotes: 0
Reputation: 66334
A reasonable value to work as a limit for
c
I thought would be the middle point betweenf
andl
Finding the mean average between two values, low
and high
, in mod len
function midPoint(low, high, len) {
var mid;
low %= len;
high %= len;
while (low < 0) low += len; // these two lines are the
while (high < low) high += len; // most important for direction
mid = (low + high) / 2; // mean average
mid %= len; // convert back to our mod
return mid;
}
So have
// works as expected beyond range of mod
midPoint( 1, -1, 9); // middle of 1..8 (mod 9) = 4.5
midPoint(-7, 5, 9); // middle of 2..5 (mod 9) = 3.5
midPoint(-6, 12, 9); // middle of 3..3 (mod 9) = 3
// and
midPoint( 2, 5, 9); // middle of 2..5 (mod 9) = 3.5
midPoint( 5, 2, 9); // middle of 5..2 (mod 9) = 8 (we went the other way around)
You don't actually have to force the mod until after the whole calculation, so if you really wanted you could do the following, but you lose direction around the loop
function midPoint(A, B, len) {
var mid;
mid = (A + B) / 2; // mean average
mid %= len; // convert back to our mod
while (mid < 0) mid += len; // always positive
return mid;
}
Notice here, however
midPoint(-6, 3, 9); // middle of 3..3 (mod 9) = 7.5
midPoint( 3, 3 + 0 * 9, 9); // middle of 3..3 (mod 9) = 3
midPoint( 3, 3 + 1 * 9, 9); // middle of 3..3 (mod 9) = 7.5
midPoint( 3, 3 + 2 * 9, 9); // middle of 3..3 (mod 9) = 3
i.e. the mid point of 3..3
(mod 9) is both 3
and 7.5
, which is true, but which way around we've gone now depends on k
(where B - A = k * len + a
)
Upvotes: 1
Reputation: 1893
I'm not sure I understand - when I define the mod function that all works:
function test() {
var i=0;
var arr = ['a', 'b', 'c', 'd'];
var f = 0; // first element
var l = arr.length - 1; // last element
var c = 0; // current element
while (true && i < 1000) {
++i;
console.log('f', f, 'l', l, 'c', c);
if (c == l) {
console.log('error');
break;
}
c = mod(c + 1, arr.length);
if (c > mod(l - f, arr.length) / 2) {
f = mod(f + 1, arr.length);
l = mod(l + 1, arr.length);
}
}
}
function mod(a,b) { return a % b;}
Seems to loop c through the possible values, and c
is never the same as the (continuously recalculated) value of l
... but I don't understand the arithmetic you're trying to apply to f
and l
there
Upvotes: 0