{"id":4383,"date":"2024-10-17T21:47:39","date_gmt":"2024-10-17T21:47:39","guid":{"rendered":"https:\/\/algocademy.com\/blog\/code-quality-in-coding-interviews-the-fizzbuzz-test-and-beyond\/"},"modified":"2026-10-15T12:51:16","modified_gmt":"2026-10-15T12:51:16","slug":"code-quality-in-coding-interviews-the-fizzbuzz-test-and-beyond","status":"publish","type":"post","link":"https:\/\/algocademy.com\/blog\/code-quality-in-coding-interviews-the-fizzbuzz-test-and-beyond\/","title":{"rendered":"The FizzBuzz Test: What It Is and Why Interviewers Use It"},"content":{"rendered":"<p>The FizzBuzz test asks you to print the numbers from 1 to 100, but print &#8220;Fizz&#8221; for multiples of 3, &#8220;Buzz&#8221; for multiples of 5, and &#8220;FizzBuzz&#8221; for multiples of both. It is trivial on purpose: interviewers use it to filter out candidates who cannot turn a short written spec into working code. If you can solve it calmly and explain your choices, you pass. The interesting part is what a good interviewer does next.<\/p>\n<h2>Where the test comes from<\/h2>\n<p>FizzBuzz is a children&#8217;s counting game. It became a programming screen after Imran Ghory wrote about it in January 2007 in a post titled <a href=\"https:\/\/imranontech.com\/2007\/01\/24\/using-fizzbuzz-to-find-developers-who-grok-coding\/\">Using FizzBuzz to Find Developers who Grok Coding<\/a>. His point was that some candidates talk well about programming but cannot actually write code, and a tiny exercise exposes that in a couple of minutes. It has been a standard first filter ever since.<\/p>\n<h2>The exact problem<\/h2>\n<ul>\n<li>Go through the numbers 1 to 100.<\/li>\n<li>If the number is divisible by 3, print &#8220;Fizz&#8221;.<\/li>\n<li>If it is divisible by 5, print &#8220;Buzz&#8221;.<\/li>\n<li>If it is divisible by both, print &#8220;FizzBuzz&#8221;.<\/li>\n<li>Otherwise print the number.<\/li>\n<\/ul>\n<p>The only trap is the third rule. If you check &#8220;divisible by 3&#8221; first, 15 prints &#8220;Fizz&#8221; and never reaches the &#8220;both&#8221; case. Most failed attempts are this exact ordering bug.<\/p>\n<h2>A correct solution<\/h2>\n<p>The version below returns a list instead of printing, so it can be tested. It builds the word for each number from the rules that match, so &#8220;FizzBuzz&#8221; appears naturally when both rules match, with no separate case to get wrong.<\/p>\n<pre><code class=\"language-javascript\">function fizzBuzz(n, rules = [[3, \"Fizz\"], [5, \"Buzz\"]]) {\n  const out = [];\n  for (let i = 1; i &lt;= n; i++) {\n    let word = \"\";\n    for (const [divisor, text] of rules) {\n      if (i % divisor === 0) word += text;\n    }\n    out.push(word || String(i));\n  }\n  return out;\n}\n\nconsole.log(fizzBuzz(15).join(\" \"));\n<\/code><\/pre>\n<p>Output:<\/p>\n<pre><code>1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz\n<\/code><\/pre>\n<p>If you want the plain version that most interviewers expect first, this Python one checks the combined case first using <code>i % 15<\/code> (15 is the least common multiple of 3 and 5):<\/p>\n<pre><code class=\"language-python\">def fizzbuzz(n):\n    result = []\n    for i in range(1, n + 1):\n        if i % 15 == 0:\n            result.append(\"FizzBuzz\")\n        elif i % 3 == 0:\n            result.append(\"Fizz\")\n        elif i % 5 == 0:\n            result.append(\"Buzz\")\n        else:\n            result.append(str(i))\n    return result\n\nprint(\" \".join(fizzbuzz(15)))\n<\/code><\/pre>\n<p>It prints the same line as above. Both versions run in O(n) time. The first version does one pass per rule for each number, so with <code>r<\/code> rules it is O(n * r), which is fine for a handful of rules.<\/p>\n<h2>Which version should you write?<\/h2>\n<p>Start with the plain one. A working, readable answer in a minute beats an elegant one that you fumble. Then, if the interviewer asks &#8220;what if the rules change?&#8221;, move to the rule-list version. Three things are worth saying out loud:<\/p>\n<ul>\n<li><strong>Why check the combined case first (or concatenate):<\/strong> it shows you understand the ordering trap.<\/li>\n<li><strong>Why return a list:<\/strong> printing inside the function makes it hard to test.<\/li>\n<li><strong>Why not <code>i % 3 == 0 and i % 5 == 0<\/code>:<\/strong> it is correct, just longer. <code>i % 15<\/code> is fine if you can say where 15 comes from, but it silently breaks if the divisors change to 4 and 6 (their common multiple is 12, not 24).<\/li>\n<\/ul>\n<h2>What interviewers look at beyond &#8220;does it work&#8221;<\/h2>\n<p>Because almost everyone who reaches an interview can produce a working FizzBuzz, interviewers use it as a conversation starter. These are the usual follow-ups.<\/p>\n<h3>Extensibility<\/h3>\n<p>&#8220;Add 7 as &#8216;Bazz&#8217;.&#8221; In the plain version this means a new branch for 7, plus 21, 35 and 105 for the combinations, which is where bugs appear. In the rule-list version it is one extra entry:<\/p>\n<pre><code class=\"language-javascript\">console.log(fizzBuzz(21, [[3, \"Fizz\"], [5, \"Buzz\"], [7, \"Bazz\"]]).slice(14).join(\" \"));\n<\/code><\/pre>\n<p>Output:<\/p>\n<pre><code>FizzBuzz 16 17 Fizz 19 Buzz FizzBazz\n<\/code><\/pre>\n<p>Note that 21 becomes &#8220;FizzBazz&#8221; with no extra code. That is the payoff of building the word from rules rather than listing combinations.<\/p>\n<h3>Testing<\/h3>\n<p>&#8220;How would you test this?&#8221; Because the function returns a list, you can assert on it. Cover the first value, a multiple of 3 only, a multiple of 5 only, a multiple of both, the length, and an empty input:<\/p>\n<pre><code class=\"language-javascript\">const assert = require(\"assert\");\nassert.deepStrictEqual(fizzBuzz(0), []);\nassert.strictEqual(fizzBuzz(3)[0], \"1\");\nassert.strictEqual(fizzBuzz(15)[14], \"FizzBuzz\");\nassert.strictEqual(fizzBuzz(100).length, 100);\nconsole.log(\"tests ok\");\n<\/code><\/pre>\n<p>This prints <code>tests ok<\/code>. The point is not the assert library; it is that you think of the boundary values (0 numbers, the first number, 15) without being prompted. For more on this habit see the post on <a href=\"https:\/\/algocademy.com\/blog\/how-to-dry-run-code-with-sample-test-cases-during-a-coding-interview\/\">dry running code with sample test cases<\/a>.<\/p>\n<h3>Readability<\/h3>\n<p>Interviewers read your code as a teammate would. Names like <code>word<\/code>, <code>divisor<\/code> and <code>fizzBuzz<\/code> are fine; <code>x<\/code>, <code>tmp<\/code> and <code>a2<\/code> are not. Avoid clever one-liners that you could not explain line by line.<\/p>\n<h3>Edge cases and inputs<\/h3>\n<p>Ask what should happen for <code>n = 0<\/code>, negative <code>n<\/code>, or a non-integer. Often the answer is &#8220;assume a positive integer&#8221;, but asking shows you notice the question exists. Also ask whether you should print or return, since the original statement says print.<\/p>\n<h3>Variants<\/h3>\n<p>Some interviewers change the rules to see whether you adapt rather than recite: no modulo operator, no <code>if<\/code> statements, print in reverse order, or make the rules come from configuration. Without modulo you can keep counters that reset at 3 and 5. Be ready to explain the trade-off, because these versions are usually less readable than the simple one.<\/p>\n<h2>Common mistakes<\/h2>\n<ul>\n<li><strong>Wrong order of checks:<\/strong> testing 3 before &#8220;both&#8221; so 15 prints &#8220;Fizz&#8221;.<\/li>\n<li><strong>Off-by-one:<\/strong> looping from 0 (0 is divisible by everything and prints &#8220;FizzBuzz&#8221;) or stopping at 99.<\/li>\n<li><strong>Printing &#8220;FizzBuzz&#8221; plus the number<\/strong> by forgetting an <code>else<\/code>.<\/li>\n<li><strong>Hard-coding 100<\/strong> inside the function with no parameter.<\/li>\n<li><strong>Freezing:<\/strong> the common failure in a real interview is nerves, not knowledge. Say the rules back, write the plain version, then improve it.<\/li>\n<\/ul>\n<h2>How to practice<\/h2>\n<p>FizzBuzz itself takes minutes to learn, so spend the effort on the habits it tests: reading a spec carefully, writing something that works first, then testing and refactoring it while talking. To practice it with step-by-step hints, AlgoCademy has a <a href=\"https:\/\/algocademy.com\/link\/?lang=js&amp;problem=fizz-buzz&amp;solution=1\">Fizz Buzz lesson in JavaScript<\/a> (a <a href=\"https:\/\/algocademy.com\/link\/?lang=py&amp;problem=fizz-buzz&amp;solution=1\">Python version<\/a> exists too). After that, the real interview questions get harder quickly, so move on to arrays, strings and hash maps rather than polishing FizzBuzz further.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What the FizzBuzz interview test is, a correct solution with tests, why interviewers ask it, and what they check beyond it: clean code and extensibility.<\/p>\n","protected":false},"author":1,"featured_media":4382,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,23],"tags":[4],"class_list":["post-4383","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-coding-interviews","category-problem-solving","tag-coding-interviews"],"_links":{"self":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/4383"}],"collection":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/comments?post=4383"}],"version-history":[{"count":3,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/4383\/revisions"}],"predecessor-version":[{"id":8935,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/4383\/revisions\/8935"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media\/4382"}],"wp:attachment":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media?parent=4383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/categories?post=4383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/tags?post=4383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}