admin管理员组

文章数量:1431406

We have a numerical array with arbitrary max values for each element. How do we increment the elements so the array would go from [0, 0, 0] to [x, y, z]?

To illustrate if the max array is [2, 1, 2] and we start the main array at [0, 0, 0] incrementing should take the main array through these steps:

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

I have written a function which stops incrementing as soon as it reaches a max of 1. Here is my code:

var maxes = [2, 1, 2];
var myArray = [0, 0, 0];

function step() {
  for(var i = 0; i < myArray.length; i++) {
    if(myArray[i] == maxes[i]) {
       continue;
    } else {
       myArray[i] = myArray[i] + 1;
       return;
    }
  }
  return false;
}

for(j = 0; j < 100; j++) {
  result = step();
  if(!result) break;
  console.log(result);
}

We have a numerical array with arbitrary max values for each element. How do we increment the elements so the array would go from [0, 0, 0] to [x, y, z]?

To illustrate if the max array is [2, 1, 2] and we start the main array at [0, 0, 0] incrementing should take the main array through these steps:

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

I have written a function which stops incrementing as soon as it reaches a max of 1. Here is my code:

var maxes = [2, 1, 2];
var myArray = [0, 0, 0];

function step() {
  for(var i = 0; i < myArray.length; i++) {
    if(myArray[i] == maxes[i]) {
       continue;
    } else {
       myArray[i] = myArray[i] + 1;
       return;
    }
  }
  return false;
}

for(j = 0; j < 100; j++) {
  result = step();
  if(!result) break;
  console.log(result);
}
Share Improve this question edited Dec 22, 2012 at 7:05 Majid Fouladpour 30.3k21 gold badges78 silver badges129 bronze badges asked Dec 20, 2012 at 21:52 user1920050user1920050 411 silver badge2 bronze badges 5
  • 2 it is hard to follow the pattern you are looking for, are you trying to calculate with base(4) ? You should at least provide a mathematical formulas to follow. – Mehdi Karamosly Commented Dec 20, 2012 at 21:55
  • @MehdiKaramosly, the formula is simple, increment the leftmost element that is still below the max for that element. If all elements are at their maxes, return false. – user1920050 Commented Dec 20, 2012 at 22:00
  • You can use a simplified version of my answer in stackoverflow./questions/13742093/… – Barmar Commented Dec 20, 2012 at 22:01
  • @Shredder, actually this could be thought of as a base n number with two exceptions (i) each digit has it's own base which is the max, and (ii) we are writing the number right to left. – user1920050 Commented Dec 20, 2012 at 22:07
  • Don't forget to upvote any answers that helped you and accept an answer if it solved it. – redolent Commented Jan 14, 2013 at 23:19
Add a ment  | 

5 Answers 5

Reset to default 1

Fair disclosure: This is my own question. I did not have access to my SO or email logins and posted this question with a new account just then created for a friend. I am not upvoting the question or him the answer. Neither would I have my friend mark my answer as accepted. Anyway, I worked on the problem and eventually came by this working code:

var maxes = [4,1,2,3];
var pattern = [0,0,0,0];

function step() {
  var t = false;
  for(var k = 0; k < pattern.length; k++) {
    t = t || (pattern[k] < maxes[k]);
  }
  if(!t) return false;
  for(k = 0; k < pattern.length; k++) {
    if(pattern[k] < maxes[k]) {
      pattern[k]++;
      return true;
    } else {
      pattern[k] = 0;
      continue;
    }
    return false;
  }
}

console.log(pattern);
var r = true;
while(r) {
  r = step();
  console.log(pattern);
}

JSBin here.

You need two loops - one for each maxes element, 4 of them currently, but I'm not sure if you plan to change it to be dynamic; and the other loop that will increment values of each element until it reaches its limit value from maxes.

You just have some bugs to work out:

var maxes   = [3, 1, 2, 1];
var myArray = [0, 0, 0, 0];

function step() {
  var changed = false;
  for(var i = 0; i < myArray.length; i++) {
    if(myArray[i] == maxes[i]) {
       continue;
    } else {
       myArray[i] = myArray[i] + 1;
       changed = true;
    }
  }
  return changed;
}

for(j = 0; j < 100; j++) {
  result = step();
  if(!result) break;
  console.log(myArray.join(", "));
}

I revisited this problem a few days ago, and refactored the code a bit.

First to understand the problem properly, it is equivalent to counting in a hybrid-base number system. In this system we have an arbitrary base per position/digit. If all the maxes are 2 for instance the problem then would be counting in base-2, but the maximum for each position could be a different number, hence, the hybrid base system.

The central function is actually very simple:

// increment in hyper system
function incr(maxes,num,digit) {
  num[digit] = num[digit] + 1;
  num[digit] = num[digit] % (maxes[digit]+1);
  if(num[digit] === 0) incr(maxes,num,digit+1);
}

And here's a working jsbin.

Here's a simpler, more efficient solution: Simply take a variable pos that stores the current position in the array. Once we've reached max at the current position, we increment the current position by 1, otherwise increment the value at the current position. And that process you just keep repeating until pos has reached the last value and the last value is at max.

var maxes = [3, 1, 2, 1];
var myArray = [0, 0, 0, 0];
var pos = 0;

while (pos < myArray.length - 1 || myArray[pos] < maxes[pos]) {
    if (myArray[pos] >= maxes[pos]) {
        myArray[pos] = 0; // to set it back to zero
        pos++;
        continue;
    } 
    myArray[pos]++;

    // Step code here
}

Works with any sized array. Here's a jsfiddle

本文标签: javascript increment numerical arrayStack Overflow