The common programming challenge, FizzBuzz, is usually phrased something like this:
Write a program which does the following.
For each of the integers from 1 to 100 inclusive:
- If the integer is divisible by 3, print
- If the integer is divisible by 5, print
- If nothing else has been printed, print the integer.
- Print a line break,
If you are just starting to learn a programming language, or just starting to learn to program in general, FizzBuzz tests a few extremely basic concepts: variables, conditionals, loops, output and escaping. I'm teaching Perl again, so I've assigned FizzBuzz as a nominal piece of homework.
Unfortunately, manually checking every FizzBuzz implementation to see that it does the correct thing is a little tiresome. And simply eyeballing the output is prone to human error. Wouldn't it be better if I had another Perl script which could mark FizzBuzz submissions for me?
metafizzbuzz.pl) is a Perl script which accepts the name of another Perl script as input, executes it, and tells you whether it implements FizzBuzz correctly or not.
MetaFizzBuzz returns a score out of 100, based on how many lines of output are correct. For example, printing "Fizz" instead of "FizzBuzz" when N is 15, 30, 45, 60, 75 or 90 loses a point. Such a person would probably score 94/100.
There are also some bonuses and penalties:
- 1 point lost for each incorrect result printed, as mentioned.
- 1 point lost if the script exits with a non-zero return code.
- 1 point lost for using the wrong separator (e.g. spaces).
- 1 point lost for stopping before 100 or continuing past 100 (e.g. fencepost errors).
- 1 point lost if the script doesn't begin with
use strict; use warnings;.
- 1 bonus point for a script which fits in a tweet (140 characters or fewer).
- 1 bonus point for a script which doesn't use conditionals (
unlessor the conditional operator,
(The bonus points are there for people who already know programming pretty well and want a challenge. The maximum possible score is 102/100 and yes, it is completely possible.)
MetaFizzBuzz has some open issues and there is limitless room for greater intelligence in evaluating results. At the time of writing:
- MetaFizzBuzz performs very basic pattern matching to detect the use of conditionals in the input implementation. This could easily yield false positives. It would be preferable to actually parse the input Perl code and build an abstract syntax tree. Unfortunately, Perl cannot be parsed.
- MetaFizzBuzz searches for
use strict; use warnings;at the very beginning of the program, and doesn't take into account the possibility of leading comments, such as a hashbang line. And, again, only simple pattern matching is used here. It's entirely possible to engineer a false positive.
- Strictly speaking, byte sequences (files) longer than 140 bytes may still "fit in a tweet". Naively using
lengthto determine this is likely to give false negatives in some edge cases.
- MetaFizzBuzz is currently helpless in the face of non-halting input programs - although, notice how the specification gives no time frame for the output, and does not even specify that the input program must halt!
- MetaFizzBuzz can get quite confused when individual terms (
"Fizz") in the expected output and the actual output stop lining up (e.g. if N = 15 is rendered as
"Fizz Buzz"rather than, as the specification requires,
"FizzBuzz"). This single error has a knock-on effect on all later lines of output.
- There should be test cases for each of MetaFizzBuzz's bonus and penalty conditions.
- MetaFizzBuzz executes arbitrary code from untrusted sources-- namely, Perl students. Erm, SECURITY??!
And, of course, this whole thing is Perl-only at the moment. It's not possible to use it to mark a Java implementation, for example.
The real reason
The real reason for me creating MetaFizzBuzz is that MetaFizzBuzz itself is an interesting programming challenge, which I intend to give to my Perl students as a future piece of homework. Implementing MetaFizzBuzz tests new areas such as executing external programs, capturing output from the same, opening and reading files, and pattern matching.
Of course, now I run into a different problem. It seems that MetaFizzBuzz's own specification ("it should tell me whether another FizzBuzz implementation is good or not") is far too fuzzy. I'll have to lock that down before continuing.
And then maybe I'll need a program that can mark MetaFizzBuzz implementations too. Gee, I wonder what that could be called.