Algorithms

HackerRank - Counting Valleys Challenge

One of HackerRank’s Warm-up Challenges in Javascript

Adam

Adam


The following solution is written in Javascript.

Problem

An avid hiker keeps meticulous records of their hikes. During the last hike that took exactly steps, for every step it was noted if it was an uphill, U, or a downhill, D step. Hikes always start and end at sea level, and each step up or down represents a unit change in altitude.

Breaking down the challenge into blocks of requirements, we get:

  • U = A uphill step
  • D = A downhill step
  • Each step represents 1 unit
  • A mountain is a sequence of consecutive steps above sea level, starting with a step up from sea level and ending with a step down to sea level.
  • A valley is a sequence of consecutive steps below sea level, starting with a step down from sea level and ending with a step up to sea level.

Example


    Steps = 8 path = [D D U U U U D D]
  

Function Description

The countingValleys function has two parameters:

  • int steps: the number of steps on the hike
  • string path: a string describing the path

Returns

  • int: the umber of valleys traversed

Sample Input


    8
    UDDDUDUU
  

Sample Output


    1
  

Explanation

If we represent _ as sea level, a step up as /, and a step down as , the hike can be drawn as:


    _/\      _
       \    /
        \/\/
  

The hiker enters and leaves one valley.

Goal

Given the sequence of up and down steps during a hike, find and print the number of valleys walked through.

Constraints & Validation

  • The number of socks n will not be more than 100
  • The number of a colour ar[i] will not be more than 100

    2 <= steps <= 10^6 (1,000,000)
    path[i] will consist of {UD}
  

The sockMerchant function expects two arguments, an integer and a sting.


    function countingValleys(steps, path) {

        if (Number.isInteger(steps)
            && steps >= 2 && steps <= Math.pow(10, 6))
        {
            // Loop through path

            // Return number of valleys traversed
        }
    }
    

Solution

We need to loop through the path string and calculate the number of mountains and valleys traversed. To do this we can increase or decrease the walkers current altitude based on the character being U or D. Each time a walker takes a downhill step when their altitude is at Sea level they enter a valley.


    let alt = 0,
        valleys = 0;

    for (var i = 0; i < path.length; i++) {
      if(str.charAt(i) == 'D')
        if(alt == 0) valleys =+ 1;
        alt -= 1;
      } else {
        alt += 1;
      }
    }
    

We can now return the number of valleys traversed.

First Attempt Solution


    function countingValleys(steps, path) {
        if (Number.isInteger(steps)
            && steps >= 2 && steps <= Math.pow(10, 6)) {

            let alt = 0,
                valleys = 0;

            for (var i = 0; i < path.length; i++) {
                if(path.charAt(i) == 'D') {
                    if(alt == 0) valleys ++;
                    alt --;
                } else {
                    alt ++;
                }
            }

            return valleys;
        }
    }

Refactored Solution

Although the solution above does work it terminated due to timeout on some of the test cases. This may be caused by the function using the .charAt() method on each loop. I noticed also that I was using path.length in the for loop instead of the steps value.

I refactored the code to test this using a simple array index instead of .charAt()


    function countingValleys(steps, path) {
        if (Number.isInteger(steps)
            && steps >= 2 && steps <= Math.pow(10, 6)) {

            let array = path.split(''),
                alt = 0,
                valleys = 0;

                for (var i = 0; i < steps; i++) {
                    if(array[i] == 'D') {
                        if(alt == 0) valleys ++;
                        alt --;
                    } else {
                        alt ++;
                    }
                }
                return valleys;
            }
        }

The solution above successfully passed each of the test cases demonstrating the importance of using methods only where necessary.