Home >Web Front-end >JS Tutorial >Codewars - Pick peaks

Codewars - Pick peaks

Patricia Arquette
Patricia ArquetteOriginal
2025-01-11 06:59:43721browse

Salutations.

Codewars - Pick peaks

I'm posting Codewars challenges and my thought process in this series. I'm using JS and Node 18 whenever possible. Just for the sake of clarity, I'm making fair use of them.

I took a break, and now I'm back. Did some challenges without posting the solution here though. Let's approach an easy challenge.

Pick peaks is a fun one. You need to find local maxima according to its mathematical definition. From GFG:

Mathematically, f (a) ≥ f (a -h) and f (a) ≥ f (a h) where h > 0, then a is called the Local maximum point.

In essence, we need to see which values are bigger than its closest neighbors. If a neighbor is missing we can't verify if it's a local maximum or not. So we won't check the borders of the array.

The following solution is not optimized. It should be one pass. Besides, I was taught to avoid using break and continue. But it does the job.

First we set the rules:

  • If the array is empty, return empty arrays. [] => {pos:[], peaks:[]}
  • If a value is less than or equal to the previous one, it's automatically discarded (plateaux will be treated in another rule). (array[i] <= array[i-1]) ? discard
  • If a value is NOT discarded by the previous rule, AND it's bigger than the next value, it's a maximum. (array[i] > array[i 1]) ? maximum
  • If a value is NOT discarded by the aforementioned rule, AND it's EQUAL TO the next value, it requires special treatment. We'll solve this later.

Second, it needs an specific return value: {pos:[], peaks:[]}
This challenge asks for position and value of the maxima.

Third, we need to set a loop for the array:
for (let i = 1 ; i < arr.length -1 ; i )
We skip the first and last value because they'll never be maxima according to the definition.

Fourth, we implement the rules:

  for (let i = 1 ; i < arr.length -1 ; i++){
    if (arr[i] <= arr[i-1]){
      continue;
    }
    if (arr[i] > arr[i+1]){
      cache.pos.push(i);
      cache.peaks.push(arr[i]);
    }
    if (arr[i] == arr[i+1]){
      // TO DO
    }
  }




</p>
<p>We'll need to refine that last part. That's the special treatment mentioned above while setting the rules. It is merely another loop that acts as a sub process:<br>
</p>

<pre class="brush:php;toolbar:false">    if (arr[i] == arr[i+1]){
      for (let j=i +1 ; j< arr.length - 1; j++){
        if (arr[j] == arr[j+1]){
          continue;
        }
        if (arr[j] < arr[j+1]){
          break;
        }
        if (arr[j] > arr[j+1]){
          cache.pos.push(i);
          cache.peaks.push(arr[i]);
        }
      }
    }

The sum of it all is this:

function pickPeaks(arr){
  let cache = {pos:[], peaks:[]};
  if (arr == false) {
    return cache;
  }

  for (let i = 1 ; i < arr.length -1 ; i++){
    if (arr[i] <= arr[i-1]){
      continue;
    }
    if (arr[i] > arr[i+1]){
      cache.pos.push(i);
      cache.peaks.push(arr[i]);
    }
    if (arr[i] == arr[i+1]){
      for (let j=i +1 ; j< arr.length - 1; j++){
        if (arr[j] == arr[j+1]){
          continue;
        }
        if (arr[j] < arr[j+1]){
          break;
        }
        if (arr[j] > arr[j+1]){
          cache.pos.push(i);
          cache.peaks.push(arr[i]);
        }
      }
    }
  }

  return cache;
}

And now let's test it... Yay! It passed! Let's submit and...

Oh no. What???

Codewars - Pick peaks

This particular test: pickPeaks([1,2,5,4,3,2,3,6,4,1,2,3,3,4,5,3,2,1,2,3,5,5,4,3])
This should return: {pos:[2,7,14,20], peaks:[5,6,5,5]}
It returns: {pos:[2,7,14,20,20], peaks:[5,6,5,5,5]}

But why? The logic is sound. And every loop is correctly... Uhmmm... Wait... It gets duplicated. Position 20, value 5. It's there twice. There's got be something wrong here:

  for (let i = 1 ; i < arr.length -1 ; i++){
    if (arr[i] <= arr[i-1]){
      continue;
    }
    if (arr[i] > arr[i+1]){
      cache.pos.push(i);
      cache.peaks.push(arr[i]);
    }
    if (arr[i] == arr[i+1]){
      // TO DO
    }
  }

After some debugging with Dev Tools, I found it. Here's the problem:

    if (arr[i] == arr[i+1]){
      for (let j=i +1 ; j< arr.length - 1; j++){
        if (arr[j] == arr[j+1]){
          continue;
        }
        if (arr[j] < arr[j+1]){
          break;
        }
        if (arr[j] > arr[j+1]){
          cache.pos.push(i);
          cache.peaks.push(arr[i]);
        }
      }
    }

It's missing a break statement. [...3,5,5,4,3] duplicates the second value because it only breaks out of the inner loop when it finds a sequence where this exit condition occurs:

function pickPeaks(arr){
  let cache = {pos:[], peaks:[]};
  if (arr == false) {
    return cache;
  }

  for (let i = 1 ; i < arr.length -1 ; i++){
    if (arr[i] <= arr[i-1]){
      continue;
    }
    if (arr[i] > arr[i+1]){
      cache.pos.push(i);
      cache.peaks.push(arr[i]);
    }
    if (arr[i] == arr[i+1]){
      for (let j=i +1 ; j< arr.length - 1; j++){
        if (arr[j] == arr[j+1]){
          continue;
        }
        if (arr[j] < arr[j+1]){
          break;
        }
        if (arr[j] > arr[j+1]){
          cache.pos.push(i);
          cache.peaks.push(arr[i]);
        }
      }
    }
  }

  return cache;
}

Otherwise it keeps going. Turns out it should exit when it finds a maximum too:

    if (arr[i] == arr[i+1]){
      for (let j=i +1 ; j< arr.length - 1; j++){
        if (arr[j] == arr[j+1]){
          continue;
        }
        if (arr[j] < arr[j+1]){
          break;
        }
        if (arr[j] > arr[j+1]){
          cache.pos.push(i);
          cache.peaks.push(arr[i]);
        }
      }
    }

FIXED:

        if (arr[j] > arr[j+1]){
          cache.pos.push(i);
          cache.peaks.push(arr[i]);
        }

Inefficient, but effective.

Take care. Drink water ???.

Previous

The above is the detailed content of Codewars - Pick peaks. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn