Overengineering Challenge: Is Number Even or Odd in 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 over engineer the
hell out of it.

The short answer

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!
);
JavaScript

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.

The long answer

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;
}
JavaScript

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.

It could have been worse

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!

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.