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!
);
JavaScriptIt 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;
}
JavaScriptNot 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 anisOdd
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!