R

E

A

C

T

O

xamples 

epeat

ode

pproach

ptimize

est

{Rainwater Collector}

The Question

You're an industrious programmer that lives off the grid. The local well that you use to fetch water has gone dry, so you've decided to collect rain water to filter. However, your collection device isn't flat.

 

PROBLEM: Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water your collection device is able to trap after raining.

Example

EXAMPLE: Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

Keep in mind...

  • Water will only gather up to the height of its reservoir walls.

 

  • We can therefore think about this problem in terms of height.

  • Water cannot be held in the first or last bar, due to no containing wall on one side.

The Approach

  • Instead of summing the volume vertically, we will think about how much volume exists in a horizontal plane at each incremental height.


  • Our solution goes about this by starting at the highest 'peak' and and summing the total amount of volume at that level then decrementing the height by 1 and repeating the process until a height of 0 is reached.

Tests to Run

// vol = 7
var a = [0,0,1,2,4,3,2,5,0,0,2,1]
console.log('collection device "a" can hold', totalVol(a))
 
// vol = 6
var b = [0,1,0,2,1,0,1,3,2,1,2,1]
console.log('collection device "b" can hold', totalVol(b))
 
// vol = 12
var c =[0,3,0,1,0,0,0,1,0,2]
console.log('collection device "c" can hold', totalVol(c))
 
// vol = 8
var d = [0,1,0,3,5,0,0,0,2,0,1]
console.log('collection device "d" can hold', totalVol(d))
 
// vol = 38
var e = [0,5,3,2,8,8,1,1,2,4,3,3,7,1,2,4,3,2]
console.log('collection device "e" can hold', totalVol(e))
function totalVol(arr) {
    var peak = Math.max.apply(null, arr);
    var vol = 0
    
    for (var height = peak; height > 0; height--) {
        var peaksAtHeightLevel = peakIndicesMaker(arr,height);
        vol += volAtLevel(peaksAtHeightLevel);
    }
    return vol;
}

function peakIndicesMaker(arr,level) {
    var peakIndices = [];

    for (var i = 0; i < arr.length; i++) {
        if(arr[i] >= level) {
            peakIndices.push(i);
        }
    }
    return peakIndices;
}
 
function volAtLevel(peakIndices) {
    var levelVol = 0
    if(peakIndices.length === 1) {
        return 0;
    } else {
        for (var i = 0; i < (peakIndices.length-1); i++) {
            levelVol += (peakIndices[i+1] - (peakIndices[i]+1));
        };
    }
    return levelVol
}

Solution with comments:

Reacto: Rainwater Collector

By Katie Peters

Reacto: Rainwater Collector

  • 1,992