function normalizeVersions(a, b) {
  a = a.slice();
  b = b.slice();

  zeroPad(a, b.length);

  // mark "x" and "*" components as equal
  for (let i = 0; i < b.length; i++) {
    const matches = b[i].match(/^[x*]$/i);
    if (matches) {
      b[i] = a[i] = '0';

      // final "*" greedily zeros all remaining components
      if (matches[0] === '*' && i === b.length - 1) {
        for (let j = i; j < a.length; j++) {
          a[j] = '0';
        }
      }
    }
  }

  zeroPad(b, a.length);

  return [a, b];
}
Normalizes `a` and `b` in preparation for comparison by doing the following:

- zero-pads `a` and `b`
- marks any "x", "X" or "*" component in `b` as equivalent by zero-ing it out
  in both `a` and `b`
- marks any final "*" component in `b` as a greedy wildcard by zero-ing it
  and all of its successors in `a`

@param {array<string>} a
@param {array<string>} b
@returns {array<array<string>>}