Joel Grus blogged about a job interview where he was asked about the ridiculous Fizz Buzz question that apparently some companies use to weed out complete frauds from their job interview process. The task is to create a program which prints the numbers from 1 to 100, but where all numbers which are a multiple of three are replaced with “fizz”, all numbers which are multiples of five are replaced with “buzz” and all numbers which are multiples of both three and five are replaced by “fizzbuzz”.
Joel somewhat comically decided to use the TensorFlow framework and solve it with machine learning. Go read his post, it’s pretty comical. Well, if you are a programming geek, it will seem comical.
For the non programmers in my audience (are there some?) this is a trivial program to write. If a programmer can’t bust out a solution to this in a minute or two, they likely have no business calling themselves a programmer. Here’s my 30 second solution (I type moderately slow):
[sourcecode lang=”cpp”]
#include <stdio.h>
int
main()
{
int i ;
for (i=1; i<=100; i++) {
if (i % 15 == 0) {
printf("fizzbuzz\n") ;
} else if (i % 3 == 0) {
printf("fizz\n") ;
} else if (i % 5 == 0) {
printf("buzz\n") ;
} else {
printf("%d\n", i) ;
}
}
return 0 ;
}
[/sourcecode]
No doubt there are some practitioners in the audience who think that this inefficient, because I compute multiple modulo operations per loop iteration. I’d probably argue that this is short and clear, and until profiling revealed it to be a performance problem, I wouldn’t change it. If people insisted that I do a single modulo per loop iteration, I’d probably replace it with something like:
[sourcecode lang=”cpp”]
#include <stdio.h>
int
main()
{
int i ;
for (i=1; i<=100; i++) {
switch (i % 15) {
case 3:
case 6:
case 9:
case 12:
printf("fizz\n") ;
break ;
case 5:
case 10:
printf("buzz\n") ;
break ;
case 0:
printf("fizzbuzz\n") ;
break ;
default:
printf("%d\n", i) ;
break ;
}
}
return 0 ;
}
[/sourcecode]
I’d submit that it is much less clear, but not too bad. I’d probably add a comment to explain the higher level idea.
If we are allowed two modulo calls per iteration, could do it this way:
[sourcecode lang=”cpp”]
int
main()
{
int i ;
for (i=1; i<=100; i++) {
bool mul3 = (i % 3 == 0) ;
bool mul5 = (i % 5 == 0) ;
if (mul3 && mul5) {
printf("fizzbuzz\n") ;
} else if (mul3) {
printf("fizz\n") ;
} else if (mul5) {
printf("buzz\n") ;
} else {
printf("%d\n", i) ;
}
}
return 0 ;
}
[/sourcecode]
I used boolean variables, which I think reads a little better, but you could obviously use integers.
What if you don’t want to any modulus calls? Well, you could use a state machine…
[sourcecode lang=”cpp”]
#include <stdio.h>
int
main()
{
int i = 1 ;
int state = 1 ;
while (i <= 100) {
switch (state) {
case 3:
case 6:
case 9:
case 12:
printf("fizz\n") ;
break ;
case 5:
case 10:
printf("buzz\n") ;
break ;
case 15:
printf("fizzbuzz\n") ;
state = 0 ;
break ;
default:
printf("%d\n", i) ;
}
state ++ ;
i++ ;
}
return 0 ;
}
[/sourcecode]
I hope I never have an interview where this is the kind of question I get asked.
seq 100 | awk ‘$1%3==0 {printf(“fizz”)} $1%5==0 {printf(“buzz”)} {print}’ | sed ‘/zz/s/[0-9]//g’
Just do it all with addition….
#include
int main() {
int i, o[101];
for (i = 0; i <= 100; i++) o[i] = 0;
for (i = 3; i <= 100; i += 3)
o[i] |= 1;
for (i = 5; i <= 100; i += 5)
o[i] |= 2;
for (i = 1; i <= 100; i++)
if (!o[i])
printf("%d\n", i);
else
printf("%s%s\n", (o[i] & 1) ? "fizz" : "", (o[i] & 2) ? "buzz" : "");
}
Not sure I like your solution, David. I’d wager that the extra storage actually makes it less efficient because of the speed of the memory hierarchy, and the fixed size of the temporary storage is not all that maintainable.