1

Firstly, apologies for the poor Title. It's the best I could come up with.

I've come up with a simple loop in Javascript which uses two variables and decrements each by 1 every other iteration. This is the code:

for(let i = j = 999; j > 0; j > i ? j-- : i--) {do_something_here}

The output you get is:

i:  999  j:  999
i:  998  j:  999
i:  998  j:  998
i:  997  j:  998
i:  997  j:  997
i:  996  j:  997
i:  996  j:  996
i:  995  j:  996
i:  995  j:  995

My question: How could I scale this to decrement any number of variables? Is there a way to modify the loop so that if I had, say, 4 indices (e.g. i, j, k, m), the code would dynamically recognise the number of indices?

Profplum
  • 89
  • 1
  • 9
  • Request for clarification: do you mean you want to be able to take n variables and have each of them decrement every n steps? Aka if you have 10 variables each one will decrement once for every 10 steps? – ChrisM Apr 05 '18 at 09:36
  • Is this a challenge or something? What's the actual purpose? – akinuri Apr 05 '18 at 09:38
  • Hi. This was inspired by me attempting Problem 4 on Project Euler (https://projecteuler.net/problem=4). I decided that it isn't the right way to solve the challenge but was inspired to try to create this loop anyway. – Profplum Apr 06 '18 at 19:28
  • To be honest, guys, I'm overwhelmed with the number and quality of responses all in one place. The techniques here should be able to help me solve a great many programming challenges in the future :) There is no clear Answer to use to mark the question as solved so I'm upvoted all of them although I most impressed by @akinuri's answer for its sheer creativity and detailed explanation. – Profplum Apr 06 '18 at 19:41
  • I suspected it might be a challenge :) Btw, have you solved the problem 4? If not, I'd like to help. – akinuri Apr 06 '18 at 21:24
  • I have not! I had to hold up my efforts for it but want to get back on it. I'll give you a shout if I get totally stuck or once I've completed it. I'd like to do as much as I can on my own at first :) – Profplum Apr 08 '18 at 22:13

6 Answers6

1

You can use an array to store as many variables you want, You can try something like this:

var iterations = 10, index = 0, arr = [999, 999]; // array of variables
console.log("i: ", arr[0], "j: ", arr[1]);
for(var k = 1; k < iterations ; k++){
  arr[index]--;
  index = (index + 1) % arr.length;
  console.log("i: ", arr[0], "j: ", arr[1]);
}
Ishpreet
  • 5,230
  • 2
  • 19
  • 35
0

You can try following

/* noOfVars -> Number of variables min. 1,
 * max -> init value of each variable */
function scaleLoop(noOfVars, max) {
  let obj = {};
  for (var i = 1; i <= noOfVars; i++) {
     obj["index" + i] = max;
  }
  
  for (var j = 1; j <= max; j++) {
     for (var i = 1; i <= noOfVars; i++) {
        obj["index" + i]--;
        console.log(obj);
     }
  }
}

scaleLoop(3, 4);
Nikhil Aggarwal
  • 28,197
  • 4
  • 43
  • 59
0

This is a problem well-suited for ES6 features for..of in combination with generator functions. Consider the following:

const parallelDecrement = function*(noVars, startingValue = 999, endingValue = 0) {
    values = Array(noVars).fill(startingValue);
    while(values[noVars-1]){
        yield values;
        let indexToDecrement = values.indexOf(values[0] + 1) % noVars;
        values[indexToDecrement  === -1 ? 0 : indexToDecrement]--;  
    }
}


for( let [i, j, k] of parallelDecrement(3) ) {
    console.log(i, j, k)
}

Or for more variables...

for( let [i, j, k, l, m] of parallelDecrement(5) ){
    console.log(i, j, k, l, m)
}

Outputs:

999 999 999 999 999
998 999 999 999 999
...
1 2 2 2 2
1 1 2 2 2
1 1 1 2 2
1 1 1 1 2
1 1 1 1 1
1 1 1 1
0 0 1 1 1
0 0 0 1 1
0 0 0 0 1
Karamell
  • 1,023
  • 9
  • 23
0

Assuming a defined number of iterations, offset per step and that you want to apply your operations in sequence to a series of variables. I would probably do this with a function:

let iterations = 100;
let offset = -1;
let values = [100, 200, 300, 100];

for(let i = 0; i < 0; i++){
    sequentialAdd(offset, values);
}

function sequentialAdd(offset, values){
    //creating a persistent local scope on the function
    //just assigning it to a variable for readability/portability
    let thisFn = sequentialAdd;
    if(typeof thisFn.index === 'undefined'){
          thisFn.index = 0;
    }
    values[thisFn.index] = values[thisFn.index] + operation;
    thisFn.index++;
    if(thisFn.index > values.length){
        thisFn.index = 0;
    }
}

Naturally by changing the variables at the start you can adapt this in many ways. E.g. you could make the iterations = the highest value in the values array.

ChrisM
  • 1,565
  • 14
  • 24
0

I can't figure out the reason to do such a thing, thus I asked in a comment if this is a challenge.

Having experimented with loops/recursions couple days ago, your problem seemed like a good challenge to me. So, I'll provide a solution using recursion and try to be thorough.


Before writing a complex recursion loop, let's get the basics. First, let's try to write the following simple for loop with recursion:

for (var i = 0; i < 10; i++) {
    console.log(i);
}

becomes

function customLoop(index, target, step, callback) {
    if (index < target) {
        callback(index);
        index += step;
        customLoop(index, target, step, callback);
    }
}

customLoop(0, 10, 1, function (index) {
    console.log(index);
});

Next, converting the for loop you provided into recursion:

for (let i = j = 999; j > 0; j > i ? j-- : i--) { console.log(i, j) }

becomes

function customLoop(a, b, callback) {
    if (b > 0) {
        callback(a, b);
        if (a < b) {
            b--;
        } else {
            a--;
        }
        customLoop(a, b, callback);
    }
}

customLoop(50, 50, function (a, b) {
    console.log(a, b);
});

Finally, writing a recursion that takes multiple values as indices. If you think of your values as a one-dimensional array, what you do, basically, is walk it two values at a time.

(I could draw a fancy graph to visualize this, but I don't have the time at the moment. So, maybe later.)

function customLoop(array, callback, startIndex) {
    var startIndex = startIndex || 0;
    if (startIndex < array.length - 1 && array[array.length - 1] > 0) {
        var index_a = startIndex;
        var index_b = index_a + 1;
        var a = array[index_a];
        var b = array[index_b];
        if (callback) {
            callback.apply(null, array);
        }
        if (a < b) {
            array[index_b]--;
            startIndex = index_b;
            if (startIndex >= array.length - 1) {
                startIndex = 0;
            }
            customLoop(array, callback, startIndex);
        } else {
            array[index_a]--;
            customLoop(array, callback, startIndex);
        }
    }
}

customLoop([20, 20, 20, 20, 20], function (a, b, c, d, e) {
    console.log(a, b, c, d, e);
});

You might need to tweak the code to make it fit your needs. Also, I don't about the performance of my solution. It might slower or faster than other solutions. So, test it out.

akinuri
  • 10,690
  • 10
  • 65
  • 102
-1

if 'j' and 'i' have the same value, why do you declare the two in the cycle?

Why do not you do like that?

for (let i = 999; i > 0; i--) {
  var j=i;
  var k=i;
  var m=i;
 // do_something_here
}
eborrallo
  • 750
  • 1
  • 8
  • 17