FizzBuzz–A Programming Question
Projects or exercises that lend themselves to many different “correct” solutions are just about the best sorts of learning experiences I can imagine. They really open the possibilities for discussion and from discussion – questions, answers, explanations – comes real learning. Recently Dennis Shaw, a student at Old Dominion University and a Microsoft Student Partner, told me about the FizzBizz exercise. (see Using FizzBuzz to Find Developers who Grok Coding for where it comes from) This is exactly that sort of multiple solution but not that difficult sort of exercise I love. Briefly stated the exercise is:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.
So there you have it. It involves using some sort of conditional of course. Nested or unnested? It can be done either way. Which way is best? Do you check for multiples of three first or five? Do you check to see if the number ISN’T one of those cases first or if it IS one of those cases? Or rather than If statements is there a different way completely? Perhaps a select/case structure? Does creating functions/methods complicate of simplify the result? If students know multiple programming languages is there one that is better for this than another (think especially about functional languages v. procedural languages). Are there special operators (like perhaps the ternary operator in C#, C/C++ and Java) that might make the code “tighter?” Is there a trade off between complication and understanding? Oh and of course, does your solution actually work?
Justify your answers. (Don’t you just just love the teacher-ness of “justify your answer?” ) I can see asking students to write up an explanation of how their solution works and why they did it that way as a means for forcing examination of the solution. And as a side benefit a lot of students can benefit from yet another writing exercise. Code that can’t be explained isn’t properly understood and that causes problems in the long run. A piece of code should not be “magic” to the person who wrote it.
There are many solutions on the Internet to the FizzBuzz question. So yes, some student might go searching for one and even try to use it. The “justify your solution” question means that they still have to understand and explain how it works and why they like it. I can’t see a student saying “I like this solution because I found it on the Internet and it works.” Well, I hope they wouldn’t try that. But if they do, grade them on how well they explain the benefits of using borrowed code and if they credited the original source properly. And of course they should also be able to explain why this solution is better than others they might have found. Surely they were not so lazy as to hand in the first solution they found?
BTW a couple of related posts of mine are Teaching, Learning and the Job Interview and Characteristics of a Good Programming Project
Comments
Anonymous
February 23, 2011
Here are a few more fizzbuzz-type questions: stackoverflow.com/.../alternate-fizzbuzz-questionsAnonymous
February 24, 2011
The comment has been removedAnonymous
February 24, 2011
One more note. You might want to check out projecteuler.net if these kids of problems tickle your fancy. =)Anonymous
February 24, 2011
Actually a site that is good for this sort of thing is http://pex4fun.com Supports C#, Visual Basic and F#.Anonymous
February 24, 2011
@Keith - if mod 15 - FizzBuzz elseif mod 5 Buzz elseif mod 3 Fizz else N - if two numbers are mutually prime the only numbers that have both of them as factors has their product as a factor.Anonymous
February 24, 2011
@anon - mod is definitely the way to go... as a math guy that's the first thing I thought of.Anonymous
February 24, 2011
I did a mathematical/binary/modular approach. Unfortunately the switch is unavoidable. https://gist.github.com/843803 Full explanation there.Anonymous
February 24, 2011
The comment has been removedAnonymous
February 24, 2011
Dim i As Integer = 1 Dim oWrite As System.IO.StreamWriter oWrite = IO.File.CreateText("C:Tempfizzbuzz.txt") While i <= 100 If (i Mod 3 = 0 And i Mod 5 = 0) Then oWrite.WriteLine(CStr(i) + " - FizzBuzz") ElseIf (i Mod 3 = 0) Then oWrite.WriteLine(CStr(i) + " - Fizz") ElseIf (i Mod 5 = 0) Then oWrite.WriteLine(CStr(i) + " - Buzz") Else oWrite.WriteLine(CStr(i)) End If i = i + 1 End While oWrite.Close()Anonymous
February 24, 2011
This is based on a drinking game called Bizz-Buzz where you drank if you didn't get the correct numbers as each in the group counted from 1 to 100. I lost a lot. But, congrats on the ones who posted the code already!Anonymous
February 24, 2011
If you work where I do, you set up a web service that will return the string to print given the integer input. duh. I am jaded.Anonymous
February 24, 2011
The comment has been removedAnonymous
February 25, 2011
fizzbuzz.pastebin.com/ytRhRLAq I love the ternaries in scripted languages, and I don't feel readability suffers because their syntax is so unique that one should know what they're looking at if they've ever encountered them before. I still think this could probably be condensed further -- just have this feeling at the back of my neck that I'm missing something -- but that almost certainly would impact readability. I'll also note that while I used "n" between integers in my sample, that was mostly because there's no practical application where this would need to be made pretty, and newline characters are two less code characters than a "<br>". :P (My apologies if this is a repost. I just tried to submit, and there was no acknowledgement once the page loaded, nor was my comment listed.)Anonymous
February 25, 2011
C# Code for (int i = 1; i <= 100; i++) { string s = ""; s = (i % 3 == 0) ? ((i%5==0)?"FizzBuzz":"Fizz") : ((i%5==0)?"Buzz":i.ToString()) ; Console.WriteLine(s); } Console.ReadLine();Anonymous
February 25, 2011
C# Code- iam dumb, reduced one more line :) for (int i = 1; i <= 100; i++) { string s = (i % 3 == 0) ? ((i%5==0)?"FizzBuzz":"Fizz") : ((i%5==0)?"Buzz":i.ToString()) ; Console.WriteLine(s); } Console.ReadLine();Anonymous
February 25, 2011
C# Code : Man iam the dumbest c# programmer around for (int i = 1; i <= 100; i++) { Console.WriteLine((i % 3 == 0) ? ((i%5==0)?"FizzBuzz":"Fizz") : ((i%5==0)?"Buzz":i.ToString())); } Console.ReadLine();Anonymous
February 25, 2011
The comment has been removedAnonymous
February 25, 2011
The comment has been removedAnonymous
February 25, 2011
Modulo was obviously my first thought, but - what about using the Sieve of Eratosthenes approach? Pseudocode: threes := bit[100] fives := bit[100] for (i := 3; i <= 100; i += 3) threes[i-1] = true; for (i := 5; i <= 100; i += 5) fives[i-1] = true; for (i := 1; i <= 100; ++i) if (threes[i-1] || fives[i-1]) if (threes[i-1]) print "Fizz" if (fives[i-1]) print "Buzz" else print i Benefit: No division is necessary! Division is much more expensive for your CPU than addition. So, depending on the context that this program is needed for, this algorithm may be much more appropriate. It sacrifices space complexity for the sake of time complexity. If you really had to, you could optimize further by replacing the "i-1" occurrences with "i" and letting the loops start and end earlier; then you would just need an "i+1" when you print out the number. But that would require commenting your code. :)Anonymous
February 25, 2011
@anon You said: ... if two numbers are mutually prime the only numbers that have both of them as factors has their product as a factor. I know this. Yet the elegance of my code is that I don't have to check for that. I save a check by simply not doing the endl till after all the checks are done.Anonymous
February 25, 2011
The comment has been removedAnonymous
February 25, 2011
Hi Alfred, I consider it is an interesting problem and "some" mathematics are necessary to investigate, maybe resolve it. A faster solution will not use "%" or "Mod" modulo operator. Should we proceed? Thank you, MirceaMirea@yahoo.comAnonymous
February 25, 2011
for(int num=0;num<=100;num++) { if(num%3==0) { if(num%5==0) {System.out.println("FizzBuzz"+num);} else System.out.println("Fizz"+num); } else if(num%5==0) { System.out.println("Buzz"+num); } else { System.out.println(num); } }Anonymous
February 25, 2011
Solutions that do not use modulus would be most interesting. As would discussion about why they are faster. In fact a lot more discussion of why options are faster or otherwise "better" are encouraged. That is in some ways more useful than just presenting a solution.Anonymous
February 25, 2011
No mods ?? Or Division!! OK. http://codepad.org/BGRFmzbq Faster? Sure. By less than a human would ever notice. ^_^Anonymous
February 25, 2011
http://codepad.org/XH0ak9Lr - a solution in C without using Mod or %Anonymous
February 25, 2011
FWIW using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FIzzBuzz { class Program { static void Main(string[] args) { var output = Enumerable.Range(1,100) .Select(i => ( (i % 3 == 0 || i % 5 == 0) ? (((i%3 == 0) ? "Fizz" : String.Empty) + ((i%5 == 0) ? "Buzz" : String.Empty)) : i.ToString())); foreach (var s in output) { Console.Write(s + " "); } Console.ReadLine(); } } }Anonymous
February 25, 2011
I could write this in any of the languages I know, but since I'm a VB.Net person by nature, I'll do that. For i As Integer = 1 To 100 If i Mod 3 = 0 Then Console.WriteLine("Fizz") ElseIf i Mod 5 = 0 Then Console.WriteLine("FizzBuzz") Else Console.WriteLine(i) End If LoopAnonymous
February 25, 2011
Not quite David. Some cases are clearly missing.Anonymous
February 25, 2011
David (and anyone else who may need an example) Your output for the first 15 numbers should look like this: 01 1 02 2 03 Fizz 04 4 05 Buzz 06 Fizz 07 7 08 8 09 Fizz 10 Buzz 11 11 12 Fizz 13 13 14 14 15 FizzBuzz After that, the "Fizz" and "Buzz" pattern repeats over and over just with different numbers in between.Anonymous
February 25, 2011
A simple list of pre-prepared answers is by far the easiest to write, to verify, to read &c. If this were for a safety-critical application, this would be the only approach that I would accept.Anonymous
February 25, 2011
The comment has been removedAnonymous
February 25, 2011
The comment has been removedAnonymous
February 25, 2011
Some of the languages (including C) allow you to write the most unreadable code only understood by the compiler and the writer. If I saw something like this on the job (yes, production code), string s = (i % 3 == 0) ? ((i%5==0)?"FizzBuzz":"Fizz") : ((i%5==0)?"Buzz":i.ToString()) ; I would reject it in the code review. Yes, it is quick, but it is not teaching the student to do a professional job. Will this person be able to maintain it in six months? Will someone else understand it? How long will it take someone else to understand it. In business, time is money. If a programmer needs to take extra time to understand this type of code (assuming that the whole program is written like this), then your business is wasting valuable time and money. Something like String output = ""; if(i % 3 == 0) output = "Fizz"; if(i % 5 == 0) output += "Buzz"; if(output.equals("")) out.print(i+"<br>"); else out.print(output+"<br>"); As a teacher preparing students for their professional life as software engineers, it is most important to instill the idea that code readability is important.Anonymous
February 25, 2011
Was playing a bit with C++ syntax and came up with this... #include <iostream> #include <iomanip> bool setFalse(bool& var) { var = false; return true; } int main() { bool printNum; for(int i = 1; i < 101; ++i) { printNum = true; std::cout<<std::setw(3)<<std::setfill('0')<<i<<std::setw(0)<<" : "; std::cout<<(i%3==0?(setFalse(printNum)?"Fizz":""):"")<<(i%5==0?(setFalse(printNum)?"Buzz":""):""); printNum?std::cout<<i:std::cout; std::cout<<std::endl; } return 0; }Anonymous
February 25, 2011
If any one have a problem about asp.net than told me i solve it send me your problem on katarmalvk@gmail.comAnonymous
February 26, 2011
A simple solution without mod. int main() { int counter3=0; int counter5=0; int flag=0; int i=0; for(i=1;i<=100;i++) { flag=1; printf("%d ",i); if(++counter3==3) {counter3=0; printf("Fizz"); flag=0;} if(++counter5==5) {counter5=0; printf("Buzz"); flag=0;} if(flag) printf("%d",i); printf("n"); } }Anonymous
February 26, 2011
My Python answer g = lambda(i):(i%3==0 and i%5==0 and 'FizzBuzz') or (i%3==0 and 'Fizz') or (i%5==0 and 'Buzz') or i for i in range(1,101): print g(i)Anonymous
February 26, 2011
Although it's not the most efficient way (it could be done with modulo), here is my solution. I've allowed expansion to an arbitrary number of search terms, as most solutions already presented are hard-coded to 3 and 5, and would make it difficult or impractical to add, for instance, "Woo" on every instance of 2 (making 30, 60 and 90 "WooFizzBuzz"). int number, i; int[] count; string output; int [] multipler = {3, 5}; // add numbers here string[] words = {"Fizz", "Buzz"}; // corresponding words count = new int[multipler.Length]; // use a count rather than modulo for (i = 0; i < count.Length; i++) count[i] = 1; for(number = 1; number <= 100; number++) { output = ""; for (i = 0; i < multipler.Length; i++) { if (count[i] == multipler[i]) { output += words[i]; count[i] = 0; } count[i]++; } if (output == "") output = number.ToString(); Console.WriteLine(output); } Console.ReadLine();Anonymous
February 27, 2011
Enumerable.Range( 1, 100 ).Select( i => i % 15 == 0 ? "FizzBuzzrn" : i % 3 == 0 ? "Fizzrn" : i% 5 == 0 ? "Buzzrn" : String.Empty ).ToList().ForEach( Console.Write ); Console.ReadLine();Anonymous
February 27, 2011
This is what happens when you don't read the instructions properly :) Now prints the number if it's not FizzBuzz/Fizz/Buzz: Enumerable.Range( 1, 100 ).Select( i => i % 15 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i.ToString() ).ToList().ForEach( Console.WriteLine ); Console.ReadLine();Anonymous
February 27, 2011
...and the fixed aggregate version: Console.Write( Enumerable.Range( 1, 100 ).Aggregate( String.Empty, ( current, i ) => current + ( i % 15 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i.ToString() ) + "rn" ) ); Console.ReadLine();Anonymous
February 27, 2011
Extensible version (similar to Adam's but more LINQy): var words = new Dictionary<int, string> {{3, "Fizz"}, {5, "Buzz"}}; Enumerable.Range( 1, 100 ).Select( i => words.Any( wordPair => i % wordPair.Key == 0 ) ? words.Where( wordPair => i % wordPair.Key == 0 ).Aggregate( String.Empty, ( current, wordPair ) => current + wordPair.Value ) : i.ToString() ).ToList().ForEach( Console.WriteLine ); Console.ReadLine();Anonymous
February 27, 2011
Would the students get any credit for pointing out that there is an infinite number of "the numbers from 1 to 100"?Anonymous
February 27, 2011
A good question. The proper answer is probably to specify Integers between 1 and 100. :-)Anonymous
February 28, 2011
The comment has been removedAnonymous
February 28, 2011
Ability to see what is missing in a specification can be an important quality. Interestingly the formation of this problem has a missing requirement. The first sentence should read "Write a program that prints the numbers from 1 to 100 in order". The words 'in order' are missing.Anonymous
March 05, 2011
// Sans strong-typing... for( var i = 1: i <= 100; i++){ var multipleOf3 = (i % 3) == 0; var multipleOf5 = (i % 5) == 0; var t = multipleOf3 ? ( multipleOf5 ? "fizzbuzz" : "fizz") : ( multipleOf5 ? "buzz" : i); print( t); } /* Advantages:Evaluate i % 3 and i % 5 only once for each i
It's kind-of readable if you are ok with ternaries
The coercion of i to a string is here left to the language, but inexpensive algorithms for this are a commodity
To implement with stronger typing, this coercion would need to be explicitly performed or delegated */