Back to Basics
Someone: “Hey, check out this juicy programming problem!”
Dan Cowan: “I can think of at least three ways of solving it.”
Does that mean Dan’s a genius? Perhaps (if you ask him, he’ll say yes).
Another possibility is that whilst learning his craft he developed the habit of thinking of alternative ways of solving the same problems. In fact, I would argue that the extent of his (coding) skills is a direct consequence of this habit.
The scenario
In the remainder of this article, to make my point, I will use PHP for no particular reason whatsoever.
Let’s pick a really super basic problem that most programmers will have faced at least once: a variable $t toggles between two known values every time function f() is invoked.
Can you, like Dan, think of at least three ways of accomplishing this basic task in PHP?
One useful way to come up with ideas is to pose constraints for yourself — extra requirements which you then try to satisfy. Here is a by-no-means exhaustive list that works for me:
- Make it obvious
- Use what you know
- Make it pretty and/or clever
- Transform it into something you know
- Make it obscure
You may use any of them in isolation or combination to form challenging requirements.
Make it obvious
This is the easy one :
$t = $the_known_value;
function f() {
global $t, $the_known_value, $the_other_known_value;
// maybe do things here …
if ($t == $the_known_value) {
$t = $the_other_known_value;
}
else {
$t = $the_known_value;
}
// perhaps do more things here …
}
Use what you know
Suppose we knew that the toggle values were only ever boolean. This is a good opportunity to exploit our knowledge of boolean operators to come up with an alternative:
$t = $the_known_value;
function f() {
global $t;
// blah, blah …
$t = !$t;
// blah, blah …
}
Reasoning about what we know allowed us to write a beautiful one-liner. Most times using what you know results in a prettier, more clever code (a requirement in our list).
Make it pretty and/or clever
What if instead we were told that the two toggle values are arbitrary numbers, say 234 and 666 or -7 and 14. This scenario is somewhat more general than the previous scenario but our strategy remains the same: we use what we know. In this case it’s very fruitful to remember the good ol’ algebra, specifically that (A + B) – B = A.
And here is our pretty and clever code:
$t = $the_known_value;
function f() {
global $t, $the_known_value, $the_other_known_value;
// blah, blah …
$t = ($the_known_value + $the_other_known_value) - $t;
// blah, blah …
}
Another glorious one-liner!
Transform it into something you know
At the other end of the you-know-something-about-the-problem spectrum there is you-know-nothing-about-the-problem, more usefully phrased as “make no assumptions”.
The “obvious” solution is particularly desirable because it’s, well, obvious and clear, but especially because, compared with the other solutions, it makes no assumptions regarding the shape or structure of the known values.
Can we still achieve a solution that:
- is not the obvious solution,
- does not care what type of objects the known values are,
- is pretty, that is, essentially makes do without a conditional, and
- is clever, that is, it uses some type of knowledge effectively?
Have a go. Take a few minutes to come up with something…
In the meantime, here is a possible line of reasoning. We already know a solution that ticks box two and three, but not box one. I am referring to the solution in the “Use what you know” section. Our goal now is to see if we can somehow transform our current scenario into that scenario.
We need to get creative, this time using what we know about the language:
$known_values = [$the_known_value, $the_other_known_value];
$index = 0;
function f() {
global $t, $index, $known_values;
// blah, blah …
$t = $known_values[$index];
$index = !$index;
// blah, blah …
}
This is how we used our knowledge of the language:
- Array indexes in PHP are zero-based, thus the first two indices of an array are 0 and 1.
- The number 0 in PHP is considered a “falsity” or equivalent to the boolean value false. Numbers other than 0 are considered “truthy”.
- PHP automatically tries to coerce the type of a variable to comply with the operator that is being applied to it. When we apply the boolean NOT operator to the numeric $index, PHP coerces the latter into a boolean.
- Similarly when the indexing brackets operator is applied to the $index the latter is coerced into an integer.
Make it obscure
I knew a person who implemented an entire genetic algorithm in one line of C++ code. The level of his knowledge of C++ was directly proportional to the amount of damage that that code inflicted to my eyes and brain.
Although it is an impressive party trick, it is generally not recommended if you work with other people unless your job is to uglify their code. Being the conscientious person I am, I’m supposed to remind you to always follow best programming practices fostering the sanity of your co-workers. However, in line with our goal in this article, this is an excellent way to push your coding skills to the limit.
For the sake of completeness we can remove one line of code from our previous solution by being a bit obscure:
$known_values = [$the_known_value, $the_other_known_value];
$index = 0;
function f() {
global $t, $index, $known_values;
//blah, blah …
$t = $known_values[$index = !$index];
//blah, blah …
}
Here we exploit the fact that PHP allows expressions to be passed to the indexing operator which means that we can move the indexing update inside the square brackets.
Conclusion
Programming is an art and I mean that in the fullest sense of the word. It is art with a purpose, and our solutions are diverse and driven by our personalities, aesthetic sense, attitudes, and aptitudes. Use this to your advantage!
Hopefully we have shown that in addition you can form basic habits that can help sharpen your craft further.
Looking forward to seeing your solutions!