7

If I have an array of [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7] and wanted to find each case of 3 consecutive numbers (whether ascending or descending), how would I do that?

Second part would be then to alert an array with the index of each of these sequences.

For ex. the previous array would return [0,4,6,7].

So far I have this... which is a rough start

var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var results = [];

for (var i = 1; i < arr.length; i++) {
    if ((arr[i] - arr[i-1] != 1) && (arr[i] - arr[i+1] != 1)) {
        results.push(arr[i]);
    }

}
alert(results);

Thanks for the help!

Thanks for the math.abs pointer. This is what I ended up doing:

var array = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var indexes = [];

for(var i=0; i < array.length; i++) {
    var diff = array[i+1] - array[i];
    if(Math.abs(diff)==1 && array[i+1]+diff == array[i+2]) {
        indexes.push(i);
    }
}
alert(indexes);
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Yasir
  • 879
  • 5
  • 13
  • 31

5 Answers5

4

It'd be interesting to know the context of this task as well... Anyway, here's my solution:

var arr     = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var results = [];
var limit   = arr.length - 1; 

var sequence = 0;
for (var i = 0; i < limit; ++i) {
  var diff = arr[i+1] - arr[i];
  if (sequence && sequence === diff) {
    results.push(i-1);
    continue;
  }
  sequence = (diff === 1 || diff === -1) // or ... Math.abs(diff) === 1
           ? diff
           : 0;
}
console.log(results);

The idea is simple: we don't need to compare two neighbors twice. ) It's enough to raise a kind of sequence flag if this comparation starts a sequence, and lower it if no sequence is there.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • There is a bug with your solution. If the first two numbers in a new sequence are the same, e.g. `var arr = [1, 1, 2, 3 ...` then it thinks it sees a solution since `sequence === diff`. In this example -1 gets pushed into the results array, since it thinks there is a sequence beginning at 0. However, kudos for your solution's readability. – gowansg May 24 '12 at 20:56
  • You could change your `if` statement to `if(sequence === diff && diff !== 0)`. – gowansg May 24 '12 at 20:58
  • Yep, somehow I failed to notice that two neighbors may be equal as well. Easily fixable, though; thanks for your observation! ) – raina77ow May 24 '12 at 21:00
3

This is a very literal approach to your question - I have only checked forwards numbers, but adding reverse would be done almost in the same way

var arr = [1, 2, 3, 4, 10, 9, 8, 9, 10, 11, 7];
var results = [];

for (var i = 0; i < arr.length; i++) {

    // if next element is one more, and one after is two more
    if (arr[i+1] == arr[i]+1 && arr[i+2] == arr[i]+2){

        // store the index of matches
        results.push(i);

        // loop through next numbers, to prevent repeating longer sequences
        while(arr[i]+1 == arr[i+1])
            i++;
    }

}
console.log(results);
Billy Moon
  • 57,113
  • 24
  • 136
  • 237
2

You need to look closely at your expression in your if statement.

It currently says:

  • If the difference between the current element and previous element is not 1, and
  • If the difference between the current element and next element is not 1

then it's a result.

So, on the face of it, that's an incorrect logical statement to determine if the current element is in the middle of a consecutive set of three.

In addition, this doesn't account for an ascending or descending set of three either.

Try figuring out, in words, what the condition would look like and go from there.

Some things to consider

  • I suggest you start going through the list from i = 2
  • Research Math.abs
Dancrumb
  • 26,597
  • 10
  • 74
  • 130
1

This is I think a simpler way to do it. First check the average of the left and right number is equal to the middle, then check that the absolute value of either neighbor is one.

var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var indexes = [];

for(var i=1; i < arr.length; i++) {
    if((arr[i-1]+arr[i+1]) / 2 == arr[i] && Math.abs(arr[i]-arr[i-1]) == 1) {
        indexes.push(i-1);
    }
}
alert(indexes);
Billy Moon
  • 57,113
  • 24
  • 136
  • 237
0
var arr = [1, 2, 3, 5, 10, 9, 8, 9, 10, 11, 7];
var results = [];

for (var i = 0; i < arr.length - 2; i++) {
    if ((arr[i+1] - arr[i] === 1) && (arr[i+2] - arr[i+1] === 1)) {
        results.push({
            i:i,
            mode:'up',
            arr:[arr[i],arr[i+1],arr[i+2]
        });
    }
    if ((arr[i+1] - arr[i] === -1) && (arr[i+2] - arr[i+1] === -1)) {
        results.push({
            i:i,
            mode:'down',
            arr:[arr[i],arr[i+1],arr[i+2]
        });
    }

}
alert(results);
robrich
  • 13,017
  • 7
  • 36
  • 63