Finding matches using regular expression

Viewed 126

How to find the length of consecutive zeros that is surrounded by ones at both ends of a binary?

For example, in 10010001 the 2 matches are 1001 and 10001

  • 1001 the length of zeroes is 2
  • 10001 the length of zeroes is 3

I used match which returned only the last one i.e. 10001.

'1010001'.match(/1(0+)1$/g)
6 Answers

You need lookahead assertions here:

console.log('1010001'.match(/10+(?=1)/g).map(function(x) {
   return x.length - 1;
}));

First, replace all '1' by '11', then remove $ - from your regular expression.

console.log('10010001'.replace(/1/g, '11').match(/1(0+)1/g));

In regular expressions, $ is a special character matching the end of the string (MDN).

But that's only half the problem. String#match captured the trailing 1 in the first group and could not create a second overlapping group for '10001'. Try using RegExp#exec instead. The regular expression is stateful, and in this case, you'll want to move the last index back one for each match you find.

var re = /10+1/g;
var str = '10010001';
var matches = [];
var result;
while ((result = re.exec(str)) !== null) {
  matches.push(result[0]);
  re.lastIndex--;
}
console.log(matches);

Instead of using Regex, I would keep it simple.

  1. Split the string on '1's
  2. Get the length of each section
  3. Remove the first and last section length because they aren't surrounded by '1's
  4. Find the highest section length

const maxNumberOfZeros = Math.max(...'000000101000100000'.split('1').map(str => str.length).slice(1, -1));
console.log(maxNumberOfZeros);

function solution(N) {    
    let s = (N >>> 0).toString(2).split('');

    let max = 0;
    //1 1 0 0 1 0 0 0 1 0
    if(s.length > 2){

        let lastDigit = s[s.length - 1];
        let firstDigit = s[0];

        while(lastDigit == '0'){
            s.pop();
            if(!s.length || s.length == 1) return 0;
            lastDigit = s[s.length - 1];
        }

        while(firstDigit == '0'){
            s.shift();
            if(!s.length || s.length == 1) return 0;
            firstDigit = s[0];
        }
        
        let x = s.join('').split('1').filter(i => i !== '').sort().reverse();

        return x.length ? x[0].length : 0;

    }

    return 0;
}

The $ within RegExp matches end of string.

You can use Array.prototype.reduce() and logic to evaluate 1 and 0 as a Boolean to determine if the sequence matches the required pattern

let nums = ["1000000001010001", "0000000101", "100000000"];
let countZerosBetweenOnes = str => 
  (res => ([...str].reduce((a, b, idx, arr) => 
    (!!+a && !+b && arr.find((n, i) => i > idx && !!+n) && res.push(+a)
    , !+a && !+b && res.length && ++res[res.length - 1], b))
    , res.sort((a, b) => a - b).pop() || 0))([]);

nums.forEach(n => console.log(countZerosBetweenOnes(n)));

Related