Search code examples
data-structuresstackrangeextractoverlap

How to implement stack data structure to range extraction (codewars task)?


I'm struggling with codewars kata called Range Extraction - that it takes a list of integers in increasing order and returns a correctly formatted string in the range format(overlapping seperate intervals).

Example solution:

([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]);
// returns "-6,-3-1,3-5,7-11,14,15,17-20"

Well in my solution, instead of getting -6,-3-1,3-5,7-11,14,15,17-20, I got the last item -6,1,5,11,15,20.

How can I enhance my solution? The code:

function solution(list){
    let result=[]
    for(let i=0;i<list.length;i++){
        let e2=list[i]
        let e1 = result[result.length-1]
        if(e2-e1==1){
            result[result.length-1]=e2
        }
        else{
          result.push(e2 )
        }
    }
    return result
}
console.log(solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]))
  

Solution

  • You are doing nothing to write consecutive integers in range format. Instead you are just replacing the previous result with the final item in the range which is exactly reflected in your solution:

    -6: this number has no "neighbors" so is fine
    1: the  final item in the first range
    5: the final item in the second range
    ...
    

    the problem is the internal logic of the loop.

    In summary, you need a while instead of an if and you need to append instead of replace:

    function solution(list){
        let result=[]
    
        for(let i=0;i<list.length;i++){
            //write first value in range to result
            result.push(list[i].toString())
            //if this is the last entry, we are done 
            if(i === list.length - 1){
                break
            }
            //initialize variables
            let e1 = list[i]
            let e2 = list[i+1]
            let isRange = false
            //run thorugh array while we get consecutive numbers
            while(e2-e1===1 && i < list.length-1){
                //modify the OUTER LOOP index variable.
                //This means when we return to the beginning of hte for loop,
                // we will be at the beginning of the next range
                i++ 
                e1 = list[i]
                e2 = list[i+1]
                isRange = true
            }
            //if there were any consecutive numbers
            if(isRange){
                //rewrite the last entry in result as a range
                result[result.length-1]+="-" + list[i].toString()
            }
        }
        return result.toString()
    }
    console.log(solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]))
    

    now, your outer loop runs through the entire array once. The inner loop will make sure the outer loop skips any items in the list that appear in a range. Finally, if the inner loop found any range at all, it will rewrite the entry as the correct range.