AM|FM

Classic Fizzbuzz




Experimenting with fizzbuzz, the classic interview question as a JS arrow function and as a C# static method using LINQ. I actually prefer the LINQ version, do you?


The Question :


Given a range of numbers, for each print :

  • ‘FizzBuzz’ if i is divisible by 3 and 5,
  • ‘Fizz’ if i is divisible by 3,
  • ‘Buzz’ if i is divisible by 5
  • the number as a string, if none of the conditions are true.

JAVASCRIPT


  1. We create a arrow function that accepts start and end as parameters to define a range.

  1. An array is created using the Array.from() method. The length of the array is calculated using the formula end - start + 1 which determines how many numbers to be evaluated.
  2. The second argument is an callback arrow function (_, i) => {...} that will be executed for each index in the array. The underscore just indicates a placeholder for a parameter that we don't need for this function. The ole' parameter skip. It is the second 'i' parameter we care about, which represents the index of the current element in the array.

  1. We initialize a output variable with let as an empty string which is going to hold the value 'Fizz', 'Buzz' or "Fizzbuzz' based on the current number's divisibility.

  1. We initialize a constant number variable. Since we are zero based we add plus 1 so that the index starts at 1 and will represent numbers between a range from x to y. This ensure the sequence starts from the specified start value.

  1. First condition... is the current number in the iteration divisible by 3 and leaves no remainder? Fizz. The number 3 fits the bill here -- 3 / 3 leaves no remainder, it is exact division. Observing the remainder is done with the modulus operator and if zero evaluates true and appends "Fizz" to the output string. We seem the same with 6. 6 / 3 is perfect division, no remainder, and thus output is Fizz.

  1. Second condition.. Is the current number in the ieration divisible by 5 and leaves no remainder? Buzz. Again, perfect division, leaving no remainder, occurs in a case like 5 or 10 and will be a "Buzz". Both conditions can be true such as the case of 15, and thus will append "FizzBuzz" to the output variable.

  1. Lastly in the console output, the output string is logged if it is not an empty string. If output variable is an empty string, the OR operator is used and prints the number by default.

    const fizzBuzz = (start, end) => 
    Array.from({ length: end - start + 1 }, (_, i) => {
        let output = '';
        const number = start + i;

        if (number % 3 === 0) output += 'Fizz';
        if (number % 5 === 0) output += 'Buzz';

        console.log(output || number);
    });

// Invocation:
fizzBuzz(5, 100);

/* SAMPLE OUTPUT 
Buzz
Fizz
7
[...]
14
FizzBuzz
[...]
*/
 




CSHARP


  1. We create a static void method "FizzBuzz" that takes two integer parameters, start and end.

  1. We create a local enumerable collection type variable that will house all of our results during the process.

  1. |RANGE PITFALL!| Here there be dragons. Wanted to detail why we use the formula end - start + 1. You might be asking yourself, why are we using the formula end - start + 1 ? If I did FizzBuzz(1,100) using Enumerable.Range(start, end) I would get 100, the same as if I did Enumerable.Range(start, end - start + 1 ) where I'd get 100 as well. Is this truly needed?

    The trouble comes in when you use a different starting number. FizzBuzz(5,100) for instance. You would get a range from 5 to 104, not 5 - 100 as you expect. What?!?
    Enumerable.Range() generates a range. A common mistake is to assume the second paramter is the end number of the range. The second parameter isn't what you'd intuitively think —- it is not the final number of the range, but rather the number of elements to generate. a. The first parameter is the starting number. For example, if it's "1", that's where the range begins. b. The second parameter represents how many numbers to generate, not the ending number. To generate the correct range, you need to use the formula end - start + 1.

    Why does this matter?

    If you call FizzBuzz(5, 100) without adjusting the second parameter, expecting a range from 5 to 100, you're in for a world of hurt. This would actually generate numbers from 5 to 104. Why? Because you're generating 100 numbers starting from 5, not ending at 100. 5 + 100 = 105 minus one for being in a zero-based system = 104

    Fixing the range:

    To ensure the range is correct (e.g., 5 to 100), you need to use formula end - start + 1. Tattoo this on your face. In this case, the calculation becomes 100 - 5 + 1 = 96. So generate 96 numbers from a start of 5 gives us 101, then minus one to account for zero-based system equals our desired range of 5 to 100. Mind blown.

  1. The LINQ Select function evaluates each "i" iteration element in the range collection. If i is divisible by both 3 and 5, it returns "FizzBuzz". If i is divisible by only 3, it returns "Fizz". If i is divisible by only 5, it returns "Buzz". Otherwise, it returns the number itself as a string.

  1. Finally we use a foreach loop to loop through the collection and out the result.


        using System;
        using System.Linq;

        public class Program
            {
            public static void Main()
            {	
                // invocation
                FizzBuzz(1, 100);
            
            } //end main
            
            public static void FizzBuzz(int start, int end)
                {
                    var fizzBuzzResults = Enumerable.Range(start, end - start + 1)
                        .Select(i =>
                            (i % 3 == 0 && i % 5 == 0) ? "FizzBuzz" :
                            (i % 3 == 0) ? "Fizz" :
                            (i % 5 == 0) ? "Buzz" :
                            i.ToString()
                        );

                    foreach (var fizzBuzzResult in fizzBuzzResults)
                    {
                        Console.WriteLine(fizzBuzzResult);
                    }
                }


            } //end program

/* SAMPLE OUTPUT
1
2
Fizz
4
Buzz
Fizz
[...]
14
FizzBuzz
[...]
 */ 

Questions? Comments? Corrections? I'm human all too human, email me at csdear138@gmail.com