All files / exercises/uniform-integers index.ts

100% Statements 33/33
90.47% Branches 19/21
100% Functions 4/4
100% Lines 32/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 10948x                           1x 7x   7x                 1x 7x     7x 7x     7x       7x         1x   1x     7x               2x         13x 1x   12x                     9x 2x     7x   7x   7x 1x       7x     7x   26x     26x 5x 5x   21x     26x     7x    
/**
 * In case B > 9, the end of the interval is not a single-digit, but A can still be.
 *
 * In that case, we want to calculate 10 - A
 *
 * If the difference is negative or equal to zero, it means that also A isn't a single-digit number
 * and we initialise the counter with 0.
 *
 * If the difference is a positive number, A is a single-digit number and we want to calculate how many
 * of them there are between A and 9 and initialise the counter with this.
 *
 * @param A the beginning of the interval
 * @returns the counter
 */
function initTheCounter(A: number): number {
  const diff = 10 - A;
 
  return diff > 0 ? diff : 0;
}
 
/**
 * Returns the first uniform number that is greater than or equal to A.
 *
 * @param A the initial number of the interval
 * @returns the first uniform number N >= A
 */
function findTheFirstUniformInteger(A: number) {
  const tokens = `${A}`.split("");
 
  // gets the left-most digit of the number and the number of digits the number is composed of
  let leftMostDigit = Number(tokens[0]);
  const numberOfDigits = tokens.length;
 
  // builds the uniform integer
  let uniformInteger = `${leftMostDigit}`.repeat(numberOfDigits);
 
  // if this number is less than A, pick the next uniform number
 
  if (Number(uniformInteger) < A) {
    // we don't need to check for the case where leftMostDigit === 9
    // because any uniform integer with a left-most digit equal to 9 will never be
    // strictly less than A
 
    leftMostDigit += 1;
 
    uniformInteger = `${leftMostDigit}`.repeat(numberOfDigits);
  }
 
  return { uniformInteger, leftMostDigit, numberOfDigits };
}
 
/**
 * @param {number} A
 * @param {number} B
 * @return {number}
 */
export function getUniformIntegerCountInInterval(A: number, B: number) {
  /*
   * Input check
   */
 
  if (!Number.isInteger(A) || !Number.isInteger(B))
    throw new Error("The two numbers in input must be integers");
 
  if (A > B || A <= 0) return 0;
 
  /*
   * Given 1 <= A <= B
   *
   * if B <= 9 then A <= 9
   *
   * This means that both ends of the intrval are single-digit numbers
   * and we can return the difference + 1 as a result
   */
 
  if (B <= 9) {
    return B - A + 1;
  }
 
  let counter = initTheCounter(A);
 
  let startInterval = A;
 
  if (counter > 0) {
    startInterval = 10;
  }
 
  let { uniformInteger, leftMostDigit, numberOfDigits } =
    findTheFirstUniformInteger(startInterval);
 
  // while the number is less or equal to B
  while (Number(uniformInteger) <= B) {
    // increase the counter
    counter += 1;
 
    // find the next uniform number
    if (leftMostDigit === 9) {
      leftMostDigit = 1;
      numberOfDigits += 1;
    } else {
      leftMostDigit += 1;
    }
 
    uniformInteger = `${leftMostDigit}`.repeat(numberOfDigits);
  }
 
  return counter;
}