JSFiddle - React, Tailwind, and code Playground

by moeishaa

JavaScript

// min number of depths to form a valley, start peak + dip + end peak
const minStreak = 3;

/**
*	Checks if a streak is valid
* A streak is valid if all dips are lower (or equal) than start and end peak
* @param {number[]} streak Current streak
* @return {boolean} True if streak is valid, false otherwise
*/
const isValid = streak => {
  let clone = [...streak],
  	startPeak = clone.shift(),
  	endPeak = clone.pop();
  return clone.every(n => n <= startPeak && n <= endPeak);
};

/**
 * Calculate flood volume
 * @param {number[]} streak Possible streak/valley to check volume of
 * @return {number} Calculated flood volume of provided streak
 */
const calcFlood = streak => {
  if (streak.length < minStreak || !isValid(streak)) return 0;
  // sort the list and dump the maximum peak, water can only rise to second highest peak
  streak = streak.sort().slice(0, -1);
  // pick where the water can rise upto
  let max = streak.pop();
  return streak.reduce((sum, current) => sum + max - current, 0);
};

/**
 * Main method to solve the problem
 * @param {number[]} valley Initial valley structure
 * @return {number} Calculate flood volume of entire valley
 */
const solve = valley => {
  let vol = 0,
    // initially streak is just the first element
    streak = [valley.shift()],
    // peak is also blindly set to first element
    peak = streak[0];

  while (valley.length) {
    if (valley[0] < peak) {
      // streak continues since the element is less than the last observed peak
      streak.push(valley.shift());
    }
    else {
      // streak has been broken, a possible valley is formed
    	streak.push(valley[0]);      
      vol += calcFlood(streak);
      // reset streak and peak to be the current element
      streak = [valley.shift()];
      peak = streak[0];
    }    
  }

  // check for possible tail valley
  vol += calcFlood(streak);
  
  return vol;
};

console.log(solve([2, 4, 5, 2, 3, 4, 6, 6, 4, 5]));	// 7
console.log(solve([3, 2, 1, 2]));	//...