a programming interview question
Technical interviews are always hard to get right, for the interviewer no less than the interviewee. Too simple and the question fails to weed out the people you don’t want. Too hard and you end up selecting for people that lucked out and heard the question or a variant before. There’s no solution, thankfully, or we couldn’t endlessly debate the problem.
Instead of asking the candidate to write code, I found it informative to show them some code and have them describe it. I didn’t invest the practice of course, like any good interview question I borrowed it from a time I was the interviewee. Here’s a sample. This code isn’t meant to particularly interesting, it’s just something to discuss.
mystery code
int
mystery(char *s) {
char t, *p = s, *q = p;
while (*q)
q++;
while (++p < --q) {
t = isupper(*q) ? tolower(*q) : toupper(*q);
*q = *p;
*p = t;
}
return (q - s);
}
discussion
First question I ask is always to describe what the function does. The next question is describe what you think the function was supposed to do. This is tricky and requires a little explanation. We haven’t been told what the function is for, so we have to guess. But based on our knowledge of what the function does do and some assumptions about the set of useful functions, is it in that set? In other words, do any of the function’s behaviors seem more likely to be bugs? And there’s the third question. What would you change or fix about this function?
A couple things to watch out for. Some people want to skip ahead and try fixing the function as their answer to question one. Some people think it doesn’t compile. It does. Lots of people complain about the variable names, which is ok, though I generally try to steer them away from superficial issues. If you do insist on renaming the variables, please don’t tell me you’d like to rename p and q to APointerToAString and ADifferentPointerToAString. Mega fail. In order to give meaningful names to the variables, you must first decide what the function does, so you should be able to answer question one without the rename. We don’t always get to work on code that looks the way we’d like, so aesthetic hangups are a big negative sign for me.
There a few things in the function which can be confusing, so I’ll offer help on any syntax or semantics questions. The test isn’t supposed to be impenetrably obfuscated, but it is supposed to be outside their comfort zone. As part of answering question one, I try to make sure we have correctly identified the behavior of each statement. The question which matters is about how all those little behaviors combine to form a function.
The biggest trap, which makes the interview interesting, is people will see what they want or expect to see. For example, they’ll generally identify the pattern of reversing a string in place, and since reversing a string is a common enough interview question, they’ll assume that’s what’s going on here. The real test is can they identify how this function differs from reversing a string. Many people can’t. Even after asking them to step through it very carefully, they will execute the function they have imagined, not the function on the paper. I’ll call this a cognitive illusion. When I proceed to ask about what bugs are present, they won’t talk about the function on the paper. They will talk about the imagined function in their head and the bugs they imagine they would have introduced had they written it. Very amusing, but also a no hire.
implications
Even a good candidate may at first blurt out the obvious answer, but with a little prompting should be able to answer correctly. Why does this matter? When would I care about differentiating between what I think a function does and what it really does? Well, how else would you describe debugging? A bad debugger tries to discover what’s not happening; a good debugger tries to discover what is happening. Being able to see the code that exists, versus the code you think exists, is an absolutely critical development skill. The people unable to focus on piercing the illusion will be the same people rewriting modules and tearing the code base apart because they just know the bug cannot be where the bug really is. (I’ve been that guy too, so I know just how unproductive it is.)
Encountered another subtle string function in the wild.
Apropos: How I coded in 1985
other
I usually finish by asking a fourth question, to rewrite the function correctly as determined by our investigation during questions two and three. A surprising number of failures turn up here. Considering they’ve been given mostly correct starter code and we’re just fixing a few bugs in it, people will go completely off the rails. I don’t know how to interpret this, the question was supposed to be a gimme. I tacked it on for a sense of closure, where even if the guts of the interview went horribly wrong, we could both push our chairs back and say, done.