skip to Main Content

I’m working through a coding interview practice question. The prompt:

A company assigns each customer a membership ID, and you are
implementing a check digit for those IDs.

The check digit should be calculated by adding up all digits in each
membership ID. If the result of the sum is a number with more than a
single digit, another iteration is required, and the digits of the
result also should be added together. This process should repeat until
a single-digit number is calculated.

Example: for membership ID ‘55555’, the sum of all digits is 25.
Because this is not a single-digit number, 2 and 5 would be added, and
the result would be 7, which is the check digit.

So I’m attempting a recursive strategy for this. I seem to have been able to get the correct answer for a variety of queries, but I can’t understand why my return in my base case is returning undefined, but the console.log just above it returns the correct value of 7. Thoughts?

function createCheckDigit(membershipId) {
  // Write the code that goes here.
  let checkDigit = membershipId;
  if ([...checkDigit].length === 1) {
    console.log(checkDigit); // this prints 7
    return checkDigit; // why doesn't this return 7?
  } else {
    let mIdList = [...checkDigit];
    sum = 0;
    for (let c in mIdList) {
      sum += Number(mIdList[c]);
    }
    createCheckDigit(sum.toString());
  };
}

console.log(createCheckDigit("55555"));

2

Answers


  1. You need add return on your recursive call

    function createCheckDigit(membershipId) {
      // Write the code that goes here.
      let checkDigit = membershipId;
      if ([...checkDigit].length === 1) {
        console.log(checkDigit); // this prints 7
        return checkDigit; // why doesn't this return 7?
      } else {
        let mIdList = [...checkDigit];
        sum = 0;
        for (let c in mIdList) {
          sum += Number(mIdList[c]);
        }
        // line below altered to return results of recursive call
        return createCheckDigit(sum.toString());
      };
    }
    
    console.log(createCheckDigit("55555")); 
    
    Login or Signup to reply.
  2. Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding things like mutation, variable reassignments, and other side-effects. check(d) can be expressed:

    • base case: if d < 10, d is a single digit, return the answer, d.
    • inductive: d is 10 or greater, check the sum of digits of d.

    where digits(d) can be expressed:

    • base case: if d < 10, d is a single digit, return [d]
    • inductive: d is 10 or greater, append the last digit, d % 10, to the remaining digits, d / 10, rounded down.

    where sum(ds) can be expressed:

    • base case: if digits ds is empty, return the empty sum, 0
    • inductive: ds has at least one number, return the result of the first digit d[0] added to the sum of the remaining digits, ds.slice(1).
    const check = d => d < 10 ? d : check(sum(digits(d)))
    
    const sum = ds => ds.length == 0 ? 0 : ds[0] + sum(ds.slice(1))
    
    const digits = d => d < 10 ? [d] : digits(d / 10 | 0).concat(d % 10)
    
    console.log(check(55555)) // 7

    Modern JS has rich support for functional style programs, but that doesn’t mean you can’t write great recursive programs using imperative counterparts. Arrow functions can omit the body and return when only a single expression is used. Here we see the familiar named functions with an ordinary body –

    function check(d) {
      return d < 10 ? d : check(sum(digits(d)))
    }
    
    function sum(ds) {
      return ds.length == 0 ? 0 : ds[0] + sum(ds.slice(1))
    }
    
    function digits(d) {
      return d < 10 ? [d] : digits((d / 10) | 0).concat(d % 10)
    }
    
    console.log(check(55555)) // 7

    Ternary expressions condition ? ifTrue : ifFalse are used to branch functional programs. All expressions evaluates to value and thus can compose together with other expressions. The imperative equivalent is if..else and instead relies on side effects such as mutation or return

    function check(d) {
      if (d < 10) return d
      return check(sum(digits(d)))
    }
    
    function sum(ds) {
      if (ds.length == 0) return 0
      return ds[0] + sum(ds.slice(1))
    }
    
    function digits(d) {
      if (d < 10) return [d]
      return digits((d / 10) | 0).concat(d % 10)
    }
    
    console.log(check(55555)) // 7
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search