Overengineering Challenge: Is Number Even or Odd in JavaScript

Josh Sherman
5 min read
Software Development JavaScript

Code golfing is fun, and makes for great blog posts. The problem is, the world is flooded with posts attempting to show you how to write the best / most concise code imaginable.

With that, I decided that it would be a fun challenge to attempt to take a simple problem, determining if a number is even or odd, and overengineer the hell out of it.

Before we get to that, here’s my one-liner to determine if a number if even or odd in JavaScript:

const isEven = n => n % 2 === 0;

console.log(
  isEven(1), // false, it's odd!
  isEven(2), // true, it's even!
);

It works by using the modulo operator to determine if there’s remainder, if so, it’s odd, otherwise, it’s even. This could easily be rewritten into an isOdd function, but you should never need both since you can negate things in your conditionals.

This next code snippet is my attempt to write the most complex isEven method I could possibly imagine. It’s not pretty folks, and it even went through a handful of revisions as I thought some of the JavaScript built-in methods I was using were a bit advanced and would be better served by looping stuff for absolutely no reason.

Keep in mind this code is a work of comedy. Actually it’s a down right tragedy. Sadder still, I’ve run into code more convoluted than this in my ~20 year software engineering career.

And for your comedic pleasure:

function isEven(number) {
  // Check if we even have a number coming in
  if (typeof number !== 'number') {
    throw new Error('Expected number type for argument');
  }

  // Create an array of known even numbers
  let evenNumbers = [];

  for (let evenNumber = 0; evenNumber <= 8; evenNumber += 2) {
    evenNumbers = evenNumbers.concat([evenNumber]);
  }

  // Break the number into digits before and after the decimal point
  const numberString = number.toString();
  const [digitsBeforeDecimal, digitsAfterDecimal] = numberString.split('.');

  // Return false if we have digits after the decimal
  if (digitsAfterDecimal) {
    return false;
  }

  // Grab the last digit so we can determine if it's even
  let lastDigitString;

  if (digitsBeforeDecimal.length > 1) {
    const digitStrings = digitsBeforeDecimal.split('');
    const numberOfDigits = digitStrings.length;

    for (let digitIndex = 0; digitIndex < numberOfDigits; digitIndex += 1) {
      lastDigitString = digitStrings[digitIndex];
    }
  } else {
    lastDigitString = digitsBeforeDecimal;
  }

  const lastDigitNumber = parseInt(lastDigitString);
  const foundEven = evenNumbers.reduce((foundEven, evenNumber) => {
    // We already found an even, return true
    if (foundEven === true) {
      return true;
    }

    // If even, return true, otherwise return previous value
    if (evenNumber === lastDigitNumber) {
      return true;
    } else {
      return foundEven;
    }
  }, false);

  return foundEven;
}

Not surprisingly, I had some bugs in that code and it was a pain in the arse to debug, as one would expect with code that’s overly complex for no apparent reason.

Where to begin on what’s wrong as well. As mentioned, I intentionally tried to avoid as much baked-in JavaScript goodness as I could in favor of manually looping through stuff. Essentially hunting and pecking around for what I needed.

The comments serve no real purpose as they are just telling you exactly what the code is doing and no explanation into any complexities / gotchas. Don’t even get me started on juggling between numbers and string or the fact that the defensive check that throws an error means the code has to be wrapped in a try/catch statement to be utilized safely.

With everything that’s horribly wrong about this code and at 50+ lines of code already, I still think it could have been worse.

How so? Well for starters, wrapping the entire thing up in a class for the sake of object oriented programming. Said class would need to be instantiated, of course making it’s usage even more convoluted without benefit. Including an isOdd method makes perfect sense for this new class, which of course would just be a copy pasta of the isEven code instead of reusing what we already have.

I found this particular exercise extremely fun and a change of course from the usual golfed posts that are out there. The most difficult part for me was abandoning just about everything I knew about JavaScript so that I could ensure the code had as many twists and turns as possible.

I’ll probably end up doing more “Overengineering Challenge” posts in the future, but in the meantime, think you could do worse? If so, throw some shitty code online and hit me up on Twitter so I can get some laughs too!

Join the Conversation

Good stuff? Want more?

Weekly emails about technology, development, and sometimes sauerkraut.

100% Fresh, Grade A Content, Never Spam.

Related Articles