General FizzBuzz

From Rosetta Code
Task
General FizzBuzz
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Write a generalized version of FizzBuzz that works for any list of factors, along with their words.

This is basically a "fizzbuzz" implementation where the user supplies the parameters.

The user will enter the max number, then they will enter the factors to be calculated along with the corresponding word to be printed.

For simplicity's sake, assume the user will input an integer as the max number and 3 factors, each with a word associated with them.


For example, given:

>20      #This is the maximum number, supplied by the user
>3 Fizz  #The user now enters the starting factor (3) and the word they want associated with it (Fizz)
>5 Buzz  #The user now enters the next factor (5) and the word they want associated with it (Buzz)
>7 Baxx  #The user now enters the next factor (7) and the word they want associated with it (Baxx)

In other words: For this example, print the numbers 1 through 20, replacing every multiple of 3 with "Fizz", every multiple of 5 with "Buzz", and every multiple of 7 with "Baxx".

In the case where a number is a multiple of at least two factors, print each of the words associated with those factors in the order of least to greatest factor.

For instance, the number 15 is a multiple of both 3 and 5; print "FizzBuzz".

If the max number was 105 instead of 20, you would print "FizzBuzzBaxx" because it's a multiple of 3, 5, and 7.

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz



11l

Translation of: Python

<lang 11l>F genfizzbuzz(factorwords, numbers)

  V sfactorwords = sorted(factorwords, key' p -> p[0])
  [String] lines
  L(num) numbers
     V words = sfactorwords.filter2((fact, wrd) -> (@num % fact) == 0).map2((fact, wrd) -> wrd).join(‘’)
     lines.append(I words != ‘’ {words} E String(num))
  R lines.join("\n")

print(genfizzbuzz([(5, ‘Buzz’), (3, ‘Fizz’), (7, ‘Baxx’)], 1..20))</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Ada

<lang Ada> with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with Ada.Containers.Generic_Array_Sort; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;

procedure Main is

  type map_element is record
     Num  : Positive;
     Word : Unbounded_String;
  end record;
  type map_list is array (Positive range <>) of map_element;
  function "<" (Left, Right : map_element) return Boolean is
  begin
     return Left.Num < Right.Num;
  end "<";
  procedure list_sort is new Ada.Containers.Generic_Array_Sort
    (Index_Type => Positive, Element_Type => map_element,
     Array_Type => map_list);
  
  procedure general_fizz_buzz (max : Positive; words : in out map_list) is
     found : Boolean;
  begin
     list_sort (words);
     for i in 1 .. max loop
        found := False;
        for element of words loop
           if i mod element.Num = 0 then
              found := True;
              Put (element.Word);
           end if;
        end loop;
        if not found then
           Put (Item => i, Width => 1);
        end if;
        New_Line;
     end loop;
  end general_fizz_buzz;
  fizzy : map_list :=
    ((3, To_Unbounded_String ("FIZZ")), (7, To_Unbounded_String ("BAXX")),
     (5, To_Unbounded_String ("BUZZ")));

begin

  general_fizz_buzz (20, fizzy);

end Main; </lang>

Output:
1
2
FIZZ
4
BUZZ
FIZZ
BAXX
8
FIZZ
BUZZ
11
FIZZ
13
BAXX
FIZZBUZZ
16
17
FIZZ
19
BUZZ

ALGOL 68

Uses a modified version of the Algol 68 Quicksort task sample. <lang algol68>BEGIN # generalised FizzBuzz #

   # prompts for an integer, reads it and returns it               #
   PROC read integer = ( STRING prompt )INT:
        BEGIN
           print( ( prompt ) );
           INT result;
           read( ( result, newline ) );
           result
        END; # read integer #
   # prompts for a string, reads it and returns it                 #
   PROC read string = ( STRING prompt )STRING:
        BEGIN
           print( ( prompt ) );
           STRING result;
           read( ( result, newline ) );
           result
        END; # read string #
   # mode to hold a factor and associated text                     #
   MODE FBFACTOR = STRUCT( INT factor, STRING text );
   #===============================================================#
   # quicksort routine for the factors, from the Algol 68 uicksort #
   # task sample                                                   #
   #---------------------------------------------------------------#
   #--- Swap function ---#
   PROC swap = (REF[]FBFACTOR array, INT first, INT second) VOID:
   (   FBFACTOR temp  = array[first];
       array[first]  := array[second];
       array[second] := temp
   );
   #--- Quick sort 3 arg function ---#
   PROC quick = (REF[]FBFACTOR array, INT first, INT last) VOID:
   (   INT       smaller := first + 1, larger  := last;
       FBFACTOR  pivot   := array[first];
       WHILE smaller <= larger DO
           WHILE array[smaller] < pivot AND smaller < last  DO smaller +:= 1 OD;
           WHILE array[larger]  > pivot AND larger  > first DO larger  -:= 1 OD; 
           IF smaller < larger THEN
               swap(array, smaller, larger); 
               smaller +:= 1;
               larger  -:= 1
           ELSE
               smaller +:= 1
           FI
       OD;
       swap(array, first, larger);    
       IF first < larger -1 THEN quick(array, first, larger-1) FI;
       IF last  > larger +1 THEN quick(array, larger+1, last)  FI
   );
   # comparison operators #
   OP < = ( FBFACTOR a, b )BOOL: factor OF a < factor OF b;
   OP > = ( FBFACTOR a, b )BOOL: factor OF a > factor OF b;
   #===============================================================#
   # get the maximum number to consider                            #
   INT max number = read integer( "Numbers reuired: " );
   # number of factors reuired                                     #
   INT max factor = 3;
   # get the factors and associated words                          #
   [ max factor ]FBFACTOR factors;
   FOR i TO max factor DO
       factor OF factors[ i ] := read integer( "Factor " + whole( i, 0 ) + ": " );
       text OF factors  [ i ] := read string( "Text for " + whole( factor OF factors[ i ], 0 ) + ": " )
   OD;
   # sort the factors into order                                   #
   quick( factors, 1, UPB factors ); 
   # play the game                                                 #
   FOR n TO max number DO
       STRING text := "";
       FOR factor TO max factor DO
           IF n MOD factor OF factors[ factor ] = 0 THEN text +:= text OF factors[ factor ] FI
       OD;
       IF text = "" THEN
           # no words applicable to n, just show the digits        #
           text := whole( n, 0 )
       FI;
       print( ( text, newline ) )
   OD

END</lang>

Output:
Numbers reuired: 20
Factor 1: 7
Text for 7: Baxx
Factor 2: 3
Text for 3: Fizz
Factor 3: 5
Text for 5: Buzz
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

AppleScript

<lang AppleScript>--------------------- GENERAL FIZZBUZZ -------------------

-- fizzEtc :: [(Int, String)] -> [Symbol] on fizzEtc(rules)

   -- A non-finite sequence of fizzEtc symbols,
   -- as defined by the given list of rules.
   script numberOrNoise
       on |λ|(n)
           script ruleMatch
               on |λ|(a, mk)
                   set {m, k} to mk
                   
                   if 0 = (n mod m) then
                       if integer is class of a then
                           k
                       else
                           a & k
                       end if
                   else
                       a
                   end if
               end |λ|
           end script
           
           foldl(ruleMatch, n, rules)
       end |λ|
   end script
   
   fmapGen(numberOrNoise, enumFrom(1))

end fizzEtc



TEST -------------------------

on run

   unlines(take(20, ¬
       fizzEtc({{3, "Fizz"}, {5, "Buzz"}, {7, "Baxx"}})))
   

end run



GENERIC ------------------------

-- enumFrom :: Enum a => a -> [a] on enumFrom(x)

   script
       property v : missing value
       on |λ|()
           if missing value is not v then
               set v to 1 + v
           else
               set v to x
           end if
           return v
       end |λ|
   end script

end enumFrom


-- fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b] on fmapGen(f, gen)

   script
       property g : mReturn(f)
       on |λ|()
           set v to gen's |λ|()
           if v is missing value then
               v
           else
               g's |λ|(v)
           end if
       end |λ|
   end script

end fmapGen


-- foldl :: (a -> b -> a) -> a -> [b] -> a on foldl(f, startValue, xs)

   tell mReturn(f)
       set v to startValue
       set lng to length of xs
       repeat with i from 1 to lng
           set v to |λ|(v, item i of xs, i, xs)
       end repeat
       return v
   end tell

end foldl


-- mReturn :: First-class m => (a -> b) -> m (a -> b) on mReturn(f)

   -- 2nd class handler function lifted into 1st class script wrapper. 
   if script is class of f then
       f
   else
       script
           property |λ| : f
       end script
   end if

end mReturn


-- take :: Int -> [a] -> [a] -- take :: Int -> String -> String on take(n, xs)

   set ys to {}
   repeat with i from 1 to n
       set v to |λ|() of xs
       if missing value is v then
           return ys
       else
           set end of ys to v
       end if
   end repeat
   return ys

end take


-- unlines :: [String] -> String on unlines(xs)

   -- A single string formed by the intercalation
   -- of a list of strings with the newline character.
   set {dlm, my text item delimiters} to ¬
       {my text item delimiters, linefeed}
   set s to xs as text
   set my text item delimiters to dlm
   s

end unlines</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

AutoHotkey

<lang AutoHotkey>; Test parameters max := 20, fizz := 3, buzz := 5, baxx := 7

Loop % max { output := "" if (Mod(A_Index, fizz) = 0) output .= "Fizz" if (Mod(A_Index, buzz) = 0) output .= "Buzz" if (Mod(A_Index, baxx) = 0) output .= "Baxx" if (output = "") FileAppend %A_Index%`n, * else FileAppend %output%`n, * } </lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

AWK

This is a two-step solution:

  • First, we get the parameters, and
    • generate a file with the list of numbers (writing directly to that file)
    • generate a custom awk-program for that special case (redirecting standard-output)
  • the custom program is run, and does the actual work to output the desired result

Input:

105
3 Fizz
5 Buzz
7 Baxx
Usage

<lang bash>awk -f fizzbuzzGenerate.awk input.txt > fizzbuzzCustom.awk awk -f fizzbuzzCustom.awk numbers.txt</lang>

Program

<lang awk># usage: awk -f fizzbuzzGen.awk > fizzbuzzCustom.awk

function Print(s) {

   print s > "/dev/stderr"

}

BEGIN { Print( "# FizzBuzz-Generate:" )

       q2 = "\""
       fN = "numbers.txt"
      #fP = "fizzbuzzCustom.awk"

}

NF==1 { Print( "# " $1 " Numbers:" )

       for( i=1; i <= $1; i++ )
           print( i ) > fN   # (!!) write to file not allowed in sandbox at ideone.com
       Print( "# Custom program:" )
       print "BEGIN {print " q2 "# CustomFizzBuzz:" q2 "} \n"
       next

}

NF==2 { Print( "# " $1 "-->" $2 ) ##

       print "$1 %  "$1" == 0 {x = x "q2 $2 q2 "}"
       next

}

END { print ""

      print "!x  {print $1; next}"
      print "    {print " q2 " " q2 ", x; x=" q2 q2 "} \n"
      print "END {print " q2 "# Done." q2 "}"
      Print( "# Done." )

}</lang>

Example output see FizzBuzz/AWK#Custom_FizzBuzz

Batch File

<lang dos>@echo off rem input range set /p "range=> "

rem input data (no error-checking) set "data_ctr=0"

input_loop

set "data=" set /p "data=> " if "%data%" equ "" goto count rem parsing data into 1-based pseudo-array set /a "data_ctr+=1" for /f "tokens=1-2 delims= " %%D in ("%data%") do (

  set "facto%data_ctr%=%%D"
  set "print%data_ctr%=%%E"

) goto input_loop

rem perform fizzbuzz now

count

setlocal enabledelayedexpansion for /l %%C in (1,1,%range%) do (

  set "out="
  for /l %%X in (1,1,%data_ctr%) do (
     set /a "mod=%%C %% facto%%X"
     if !mod! equ 0 set "out=!out!!print%%X!"
  )
  if not defined out (echo %%C) else (echo !out!)

) pause exit /b 0</lang>

Output:
> 20
> 3 Fizz
> 5 Buzz
> 7 Baxx
>
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz
Press any key to continue . . .

BBC BASIC

This implementation (unlike some of the ones given on this page...) fully obeys the specification, in that it prompts the user for the parameters at run time. It also allows users to specify as many factors as they want, rather than limiting them to three. <lang bbcbasic>REM >genfizzb INPUT "Maximum number: " max% INPUT "Number of factors: " n% DIM factors%(n% - 1) DIM words$(n% - 1) FOR i% = 0 TO n% - 1

   INPUT "> " factor$
   factors%(i%) = VAL(LEFT$(factor$, INSTR(factor$, " ") - 1))
   words$(i%) = MID$(factor$, INSTR(factor$, " ") + 1)

NEXT FOR i% = 1 TO max%

   matched% = FALSE
   FOR j% = 0 TO n% - 1
       IF i% MOD factors%(j%) = 0 THEN
           PRINT words$(j%);
           matched% = TRUE
       ENDIF
   NEXT
   IF matched% THEN PRINT ELSE PRINT;i%

NEXT</lang> Output:

Maximum number: 20
Number of factors: 3
> 3 Fizz
> 5 Buzz
> 7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

C

<lang C>

  1. include <stdio.h>
  2. include <stdlib.h>

struct replace_info {

   int n;
   char *text;

};

int compare(const void *a, const void *b) {

   struct replace_info *x = (struct replace_info *) a;
   struct replace_info *y = (struct replace_info *) b;
   return x->n - y->n;

}

void generic_fizz_buzz(int max, struct replace_info *info, int info_length) {

   int i, it;
   int found_word;
   for (i = 1; i < max; ++i) {
       found_word = 0;
       /* Assume sorted order of values in the info array */
       for (it = 0; it < info_length; ++it) {
           if (0 == i % info[it].n) {
               printf("%s", info[it].text);
               found_word = 1;
           }
       }
       if (0 == found_word)
           printf("%d", i);
       printf("\n");
   }

}

int main(void) {

   struct replace_info info[3] = {
       {5, "Buzz"},
       {7, "Baxx"},
       {3, "Fizz"}
   };
   /* Sort information array */
   qsort(info, 3, sizeof(struct replace_info), compare);
   /* Print output for generic FizzBuzz */
   generic_fizz_buzz(20, info, 3);
   return 0;

} </lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

C#

Not extremely clever and doesn't use anything too fancy. <lang csharp> using System;

public class GeneralFizzBuzz {

   public static void Main() 
   {
       int i;
       int j;
       int k;
       
       int limit;
       
       string iString;
       string jString;
       string kString;
       Console.WriteLine("First integer:");
       i = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("First string:");
       iString = Console.ReadLine();
       Console.WriteLine("Second integer:");
       j = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("Second string:");
       jString = Console.ReadLine();
       Console.WriteLine("Third integer:");
       k = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("Third string:");
       kString = Console.ReadLine();
       Console.WriteLine("Limit (inclusive):");
       limit = Convert.ToInt32(Console.ReadLine());
       for(int n = 1; n<= limit; n++)
       {
           bool flag = true;
           if(n%i == 0)
           {
               Console.Write(iString);
               flag = false;
           }
           if(n%j == 0)
           {
               Console.Write(jString);
               flag = false;
           }
           if(n%k == 0)
           {
               Console.Write(kString);
               flag = false;
           }
           if(flag)
               Console.Write(n);
           Console.WriteLine();
       }
   }

} </lang>

C++

<lang cpp>

  1. include <algorithm>
  2. include <iostream>
  3. include <vector>
  4. include <string>

class pair { public:

   pair( int s, std::string z )            { p = std::make_pair( s, z ); }
   bool operator < ( const pair& o ) const { return i() < o.i(); }
   int i() const                           { return p.first; }
   std::string s() const                   { return p.second; }

private:

   std::pair<int, std::string> p;

}; void gFizzBuzz( int c, std::vector<pair>& v ) {

   bool output;
   for( int x = 1; x <= c; x++ ) {
       output = false;
       for( std::vector<pair>::iterator i = v.begin(); i != v.end(); i++ ) {
           if( !( x % ( *i ).i() ) ) {
               std::cout << ( *i ).s();
               output = true;
           }
       }
       if( !output ) std::cout << x;
       std::cout << "\n";
   }

} int main( int argc, char* argv[] ) {

   std::vector<pair> v;
   v.push_back( pair( 7, "Baxx" ) );
   v.push_back( pair( 3, "Fizz" ) );
   v.push_back( pair( 5, "Buzz" ) );
   std::sort( v.begin(), v.end() );
   gFizzBuzz( 20, v );
   return 0;

} </lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Caché ObjectScript

<lang Caché ObjectScript>GENFIZBUZZ(MAX,WORDS,NUMBERS)

   ; loop until max, casting numeric to avoid errors
   for i=1:1:+MAX {
       set j = 1
       set descr = ""
       
       ; assumes NUMBERS parameter is comma-delimited
       while (j <= $length(NUMBERS,",")) {
           if ((i # $piece(NUMBERS,",",j,j)) = 0) {
               
               ; build descriptor string, again assuming comma-delimited WORDS parameter
               set descr = descr_$piece(WORDS,",",j,j)
           }
           
           set j = j + 1
       }    ; check list of numbers
       
       ; output values to screen
       write " "_$case(descr,"":i,:descr)
   }    ; next value until MAX
   
   quit</lang>


Output:
SAMPLES>do ^GENFIZBUZZ(12,"FIN,FANG,FOOM","2,3,4")
 1 FIN FANG FINFOOM 5 FINFANG 7 FINFOOM FANG FIN 11 FINFANGFOOM  

Ceylon

<lang ceylon>shared void run() {

print("enter the max value"); assert(exists maxLine = process.readLine(), exists max = parseInteger(maxLine));

print("enter your number/word pairs enter a blank line to stop");

variable value divisorsToWords = map<Integer, String> {};

while(true) { value line = process.readLine(); assert(exists line); if(line.trimmed.empty) { break; } value pair = line.trimmed.split().sequence(); if(exists first = pair.first, exists integer = parseInteger(first), exists word = pair[1]) { divisorsToWords = divisorsToWords.patch(map {integer -> word}); } }

value divisors = divisorsToWords.keys.sort(byIncreasing(Integer.magnitude)); for(i in 1..max) { value builder = StringBuilder(); for(divisor in divisors) { if(divisor.divides(i), exists word = divisorsToWords[divisor]) { builder.append(word); } } if(builder.empty) { print(i); } else { print(builder.string); } } }</lang>

Clojure

<lang Clojure>(defn fix [pairs]

 (map second pairs))

(defn getvalid [pairs n]

 (filter (fn [p] (zero? (mod n (first p))))
         (sort-by first pairs)))

(defn gfizzbuzz [pairs numbers]

 (interpose "\n"
            (map (fn [n] (let [f (getvalid pairs n)]
                           (if (empty? f)
                             n
                             (apply str
                                    (fix f)))))
                 numbers)))</lang>

Usage:

user#=> (def pairs [[5 "Buzz"] [3 "Fizz"] [7 "Baxx"]])
#'user/pairs
user#=> (println (apply str (gfizzbuzz pairs (range 1 21))))
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz
nil

Common Lisp

<lang Lisp> (defun fizzbuzz (limit factor-words)

 (loop for i from 1 to limit
    if (assoc-if #'(lambda (factor) (zerop (mod i factor))) factor-words)
    do (loop for (factor . word) in factor-words
          when (zerop (mod i factor)) do (princ word)
          finally (fresh-line))
    else do (format t "~a~%" i)))

(defun read-factors (&optional factor-words)

 (princ "> ")
 (let ((input (read-line t nil)))
   (cond ((zerop (length input))
          (sort factor-words #'< :key #'car))
         ((digit-char-p (char input 0))
          (multiple-value-bind (n i) (parse-integer input :junk-allowed t)
            (read-factors (acons n (string-trim " " (subseq input i))
                                 factor-words))))
         (t (write-line "Invalid input.")
            (read-factors factor-words)))))

(defun main ()

 (loop initially (princ "> ")
    for input = (read-line t nil)
    until (and (> (length input) 0)
               (digit-char-p (char input 0))
               (not (zerop (parse-integer input :junk-allowed t))))
    finally (fizzbuzz (parse-integer input :junk-allowed t) (read-factors))))

</lang>

Crystal

<lang Crystal> counter = 0

puts "Enter a maximum number:" limit = gets

puts "Enter the first integer for factoring:" first_int = gets puts "Enter the name of the first integer:" first_int_name = gets

puts "Enter the second integer for factoring:" second_int = gets puts "Enter the name of the second integer:" second_int_name = gets

puts "Enter the third integer for factoring:" third_int = gets puts "Enter the name of the third integer:" third_int_name = gets

if (limit &&

  first_int &&
  second_int &&
  third_int &&
  first_int_name &&
  second_int_name &&
  third_int_name)
 limit = limit.chomp.to_i
 first_int = first_int.chomp.to_i
 second_int = second_int.chomp.to_i
 third_int = third_int.chomp.to_i
 while limit > counter
   counter += 1
   if (counter % first_int) == 0 && (counter % second_int) == 0 && (counter % third_int) == 0
     puts first_int_name + second_int_name + third_int_name
   elsif (counter % first_int) == 0 && (counter % second_int) == 0
     puts first_int_name + second_int_name
   elsif (counter % first_int) == 0
     puts first_int_name
   elsif (counter % second_int) == 0
     puts second_int_name
   elsif (counter % third_int) == 0
     puts third_int_name
   else
     puts counter
   end
 end

else

 exit

end </lang>

D

<lang D>import core.stdc.stdlib; import std.stdio;

void main() {

   int limit;
   write("Max number (>0): ");
   readf!"%d\n"(limit);
   if (limit <= 0) {
       writeln("The max number to consider must be greater than zero.");
       exit(1);
   }
   int terms;
   write("Terms (>0): ");
   readf!"%d\n"(terms);
   if (terms <= 0) {
       writeln("The number of terms to consider must be greater than zero.");
       exit(1);
   }
   int[] factors = new int[terms];
   string[] words = new string[terms];
   for (int i=0; i<terms; ++i) {
       write("Factor ", i+1, " and word: ");
       readf!"%d %s\n"(factors[i], words[i]);
       if (factors[i] <= 0) {
           writeln("The factor to consider must be greater than zero.");
           exit(1);
       }
   }
   foreach(n; 1..limit+1) {
       bool print = true;
       for (int i=0; i<terms; ++i) {
           if (n % factors[i] == 0) {
               write(words[i]);
               print = false;
           }
       }
       if (print) {
           writeln(n);
       } else {
           writeln();
       }
   }

}</lang>

Output:
Max number (>0): 20
Terms (>0): 3
Factor 1 and word: 3 Fizz
Factor 2 and word: 5 Buzz
Factor 3 and word: 7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Elixir

Translation of: Ruby

<lang elixir>defmodule General do

 def fizzbuzz(input) do
   [num | nwords] = String.split(input)
   max = String.to_integer(num)
   dict = Enum.chunk(nwords, 2) |> Enum.map(fn[n,word] -> {String.to_integer(n),word} end)
   Enum.each(1..max, fn i ->
     str = Enum.map_join(dict, fn {n,word} -> if rem(i,n)==0, do: word end)
     IO.puts if str=="", do: i, else: str
   end)
 end

end

input = """ 105 3 Fizz 5 Buzz 7 Baxx """ General.fizzbuzz(input)</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz
FizzBaxx
...
Buzz
101
Fizz
103
104
FizzBuzzBaxx

Erlang

<lang erlang> %%% @doc Implementation of General FizzBuzz %%% @see https://rosettacode.org/wiki/General_FizzBuzz -module(general_fizzbuzz). -export([run/2]). -spec run(N :: pos_integer(), Factors :: list(tuple())) -> ok.

fizzbuzz(N, [], []) ->

   integer_to_list(N);

fizzbuzz(_, [], Result) ->

   lists:flatten(lists:reverse(Result));

fizzbuzz(N, Factors, Result) ->

   [{Factor, Output}|FactorsRest] = Factors,
   NextResult = case N rem Factor of
       0 -> [Output|Result];
       _ -> Result
   end,
   
   fizzbuzz(N, FactorsRest, NextResult).

run(N, Factors) ->

   lists:foreach(
       fun(S) -> io:format("~s~n", [S]) end,
       [fizzbuzz(X, Factors, []) || X <- lists:seq(1, N)]
   ).

</lang> Usage:

    $ erl
    1> c(general_fizzbuzz).
    2> general_fizzbuzz:run(105, [{3, "Fizz"}, {5, "Buzz"}, {7, "Baxx"}]).
Output:

1 2 Fizz 4 Buzz Fizz Baxx 8 Fizz Buzz ... Fizz 97 Baxx Fizz Buzz 101 Fizz 103 104 FizzBuzzBaxx ok

Factor

<lang factor>USING: assocs combinators.extras io kernel math math.parser math.ranges prettyprint sequences splitting ; IN: rosetta-code.general-fizzbuzz

prompt ( -- str ) ">" write readln ;
get-factor ( -- seq )
   prompt " " split first2 [ string>number ] dip
   { } 2sequence ;
get-input ( -- assoc n )
   prompt string>number [1,b] [ get-factor ] thrice
   { } 3sequence swap ;
   
fizzbuzz ( assoc n -- )
   swap dupd [ drop swap mod 0 = ] with assoc-filter
   dup empty? [ drop . ] [ nip values concat print ] if ;
   
main ( -- ) get-input [ fizzbuzz ] with each ;

MAIN: main</lang>

Output:
>20
>3 Fizz
>5 Buzz
>7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Forth

Uses GForth specific words ']]' and '[['. If your forth does not have them: Sequence ']] A B C .. [[' is equivalent with 'postpone A postpone B postpone C ..' <lang Forth>\ gfb.fs - generalized fizz buzz

times ( xt n -- )

BEGIN dup WHILE 1- over swap 2>r execute 2r> REPEAT 2drop

\ 'Domain Specific Language' compiling words \ -- First comment: stack-effect at compile-time \ -- Second comment: stack efect of compiled sequence

]+[ ( u ca u -- ) ( u f -- u f' )

2>r >r ] ]] over [[ r> ]] literal mod 0= IF [[ 2r> ]] sliteral type 1+ THEN [ [[

]fb ( -- xt ) ( u f -- u+1 )

]] IF space ELSE dup u. THEN 1+ ; [[

fb[ ( -- ) ( u -- u 0  ;'u' is START-NUMBER )

:noname 0 ]] literal [ [[

\ Usage: START-NUMBER COMPILING-SEQUENCE U times drop ( INCREASED-NUBER ) \ Example: \ 1 fb[ 3 s" fizz" ]+[ 5 s" buzz" ]+[ 7 s" dizz" ]+[ ]fb 40 times drop </lang>

Output:
gforth gfb.fs --evaluate '1 fb[ ]fb 40 times drop cr bye'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 
gforth gfb.fs --evaluate '1 fb[ 3 s" F" ]+[ 5 s" B" ]+[ 7 s" G" ]+[ ]fb 40 times drop cr bye'
1 2 F 4 B F G 8 F B 11 F 13 G FB 16 17 F 19 B FG 22 23 F B 26 F G 29 FB 31 32 F 34 BG F 37 38 F B 

FreeBASIC

Translation of: BBC BASIC

<lang freebasic>' version 01-03-2018 ' compile with: fbc -s console

Dim As UInteger f(), factor, c, i, n Dim As Integer max Dim As String w(), word Dim As boolean flag

Do

   Input "Enter maximum number, if number < 1 then the program wil end ", max
   If max < 1 Then Exit Do
   Print
   While c = 0 Or c > max
       Input "Total number of factors ", c
   Wend
   c -= 1
   ReDim f(c), w(c)
   Print
   For i = 0 To c
       Input "Enter factor and word, separated by a comma ", factor, word
       f(i) = factor
       w(i) = word
   Next


   While flag = FALSE
       flag = TRUE
       For n = 0 To c-1
           For i = 1 To c
               If f(n) > f(i) Then
                   flag = FALSE
                   Swap f(n), f(i)
                   Swap w(n), w(i)
               End If
           Next
       Next
   Wend
   For n = 1 To max
       flag = FALSE
       For i = 0 To c
           If n Mod f(i) = 0 Then
               flag = TRUE
               Print w(i);
           End If
       Next
       Print IIf(flag , "", Str(n))
   Next
   Exit Do

Loop

' empty keyboard buffer While Inkey <> "" : Wend Print : Print "hit any key to end program" Sleep End</lang>

Output:
Enter maximum number, if number < 1 then the program wil end 110

Total number of factors 3

Enter factor and word, separated by a comma 3, Fizz
Enter factor and word, separated by a comma 5, Buzz
Enter factor and word, separated by a comma 7, Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
...
101
Fizz
103
104
FizzBuzzBaxx
106
107
Fizz
109
Buzz

Go

<lang Go> package main

import ( "fmt" )

const numbers = 3

func main() {

//using the provided data max := 20 words := map[int]string{ 3: "Fizz", 5: "Buzz", 7: "Baxx", } keys := []int{3, 5, 7} divisible := false for i := 1; i <= max; i++ { for _, n := range keys { if i % n == 0 { fmt.Print(words[n]) divisible = true } } if !divisible { fmt.Print(i) } fmt.Println() divisible = false }

}</lang>

Groovy

<lang Groovy>def log = (1..40).each {Integer value -> log +=(value %3 == 0) ? (value %5 == 0)? 'FIZZBUZZ\n':(value %7 == 0)? 'FIZZBAXX\n':'FIZZ\n'

                                   :(value %5 == 0) ? (value %7 == 0)? 'BUZBAXX\n':'BUZZ\n'
                                   :(value %7 == 0) ?'BAXX\n'
                                   :(value+'\n')}

println log </lang>

1
2
FIZZ
4
BUZZ
FIZZ
BAXX
8
FIZZ
BUZZ
11
FIZZ
13
BAXX
FIZZBUZZ
16
17
FIZZ
19
BUZZ
FIZZBAXX
22
23
FIZZ
BUZZ
26
FIZZ
BAXX
29
FIZZBUZZ
31
32
FIZZ
34
BUZBAXX
FIZZ
37
38
FIZZ
BUZZ

Haskell

<lang haskell>fizz :: (Integral a, Show a) => a -> [(a, String)] -> String fizz a xs

   | null result = show a
   | otherwise   = result
   where result = concatMap (fizz' a) xs
         fizz' a (factor, str)
             | a `mod` factor == 0 = str
             | otherwise           = ""

main = do

   line <- getLine
   let n = read line
   contents <- getContents
   let multiples = map (convert . words) $ lines contents
   mapM_ (\ x -> putStrLn $ fizz x multiples) [1..n]
   where convert [x, y] = (read x, y)

</lang>

Or, as a function which takes a list of rules as an argument:

<lang haskell>type Rule = (Int, String)


FIZZETC (USING RULE SET) ---------------

fizzEtc :: [(Int, String)] -> [String] fizzEtc rules = foldr nextLine [] [1 ..]

 where
   nextLine x a
     | null noise = show x : a
     | otherwise = noise : a
     where
       noise = foldl reWrite [] rules
       reWrite s (m, k)
         | 0 == rem x m = s <> k
         | otherwise = s



TEST OF SAMPLE RULES -----------------

fizzTest :: [String] fizzTest = fizzEtc [(3, "Fizz"), (5, "Buzz"), (7, "Baxx")]

main :: IO () main = mapM_ putStrLn $ take 20 fizzTest </lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

J

The trick here involves looking for where the factors evenly divide the counting numbers. Where no factor is relevant we use the counting number, an in the remaining cases we use the string which corresponds to the factor:

<lang J>genfb=:1 :0

 b=. * x|/1+i.y
 >,&":&.>/(m#inv"_1~-.b),(*/b)#&.>1+i.y

)</lang>

Example use:

<lang J> 3 5 7 ('Fizz';'Buzz';'Baxx')genfb 20 1 2 Fizz 4 Buzz Fizz Baxx 8 Fizz Buzz 11 Fizz 13 Baxx FizzBuzz 16 17 Fizz 19 Buzz </lang>

For our example, b looks like this:

<lang J>1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1</lang>

*/b gives us 1s where we want numbers and 0s where we want to plug in the strings:

<lang J> */*3 5 7|/1+i.20 1 1 0 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 1 0</lang>

m is our strings, and #inv expands values out to match a selection. So, in our example, m#inv"_1~-.b looks like this:

<lang J>┌┬┬────┬┬────┬────┬────┬┬────┬────┬┬────┬┬────┬────┬┬┬────┬┬────┐ │││Fizz││ │Fizz│ ││Fizz│ ││Fizz││ │Fizz│││Fizz││ │ ├┼┼────┼┼────┼────┼────┼┼────┼────┼┼────┼┼────┼────┼┼┼────┼┼────┤ │││ ││Buzz│ │ ││ │Buzz││ ││ │Buzz│││ ││Buzz│ ├┼┼────┼┼────┼────┼────┼┼────┼────┼┼────┼┼────┼────┼┼┼────┼┼────┤ │││ ││ │ │Baxx││ │ ││ ││Baxx│ │││ ││ │ └┴┴────┴┴────┴────┴────┴┴────┴────┴┴────┴┴────┴────┴┴┴────┴┴────┘</lang>

All that remains is to assemble these pieces into the final result...

Java

<lang java>public class FizzBuzz {

   public static void main(String[] args) {
       Sound[] sounds = {new Sound(3, "Fizz"), new Sound(5, "Buzz"),  new Sound(7, "Baxx")};
       for (int i = 1; i <= 20; i++) {
           StringBuilder sb = new StringBuilder();
           for (Sound sound : sounds) {
               sb.append(sound.generate(i));
           }
           System.out.println(sb.length() == 0 ? i : sb.toString());
       }
   }
   private static class Sound {
       private final int trigger;
       private final String onomatopoeia;
       public Sound(int trigger, String onomatopoeia) {
           this.trigger = trigger;
           this.onomatopoeia = onomatopoeia;
       }
       public String generate(int i) {
           return i % trigger == 0 ? onomatopoeia : "";
       }
   }

}</lang>


For a more complete example see jFizzBuzz

JavaScript

ES5

In a functional style of JavaScript, with two nested reduce folds – one through the integer series, and one through the series of rules.

First as compacted by Google's Closure compiler: <lang JavaScript>function fizz(d, e) {

 return function b(a) {
   return a ? b(a - 1).concat(a) : [];
 }(e).reduce(function (b, a) {
   return b + (d.reduce(function (b, c) {
     return b + (a % c[0] ? "" : c[1]);
   }, "") || a.toString()) + "\n";
 }, "");

}</lang>

and then in the original expanded form, for better legibility:

<lang JavaScript>function fizz(lstRules, lngMax) {

   return (
       function rng(i) {
           return i ? rng(i - 1).concat(i) : []
       }
   )(lngMax).reduce(
       function (strSeries, n) {
           // The next member of the series of lines:
           // a word string or a number string
           return strSeries + (
               lstRules.reduce(
                   function (str, tplNumWord) {
                       return str + (
                           n % tplNumWord[0] ?  : tplNumWord[1]
                       )
                   }, 
               ) || n.toString()
           ) + '\n';
           
       }, 
   );

}

fizz([[3, 'Fizz'], [5, 'Buzz'], [7, 'Baxx']], 20);</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz


ES6

<lang JavaScript>// range :: Int -> Int -> [Int] const range = (min, max) =>

 Array.from({ length: max - min }, (_, i) => min + i)

const defaultRules = Object.freeze([

 [3, 'Fizz'],
 [5, 'Buzz'],
 [7, 'Baxx'],

])

// fizzBuzz :: Int -> Int, String -> String const fizzBuzz = (max, rules = defaultRules) =>

 range(1, max + 1).map(n =>
   rules.reduce((words, [factor, word]) =>
     words + (n % factor ?  : word), 
   ) || n
 ).join('\n')

console.log(fizzBuzz(20))</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Julia

For simplicity, assume that the user will enter valid input. <lang Julia>function fizzbuzz(triggers :: Vector{Tuple{Int, ASCIIString}}, upper :: Int)

   for i = 1 : upper
       triggered = false
       for trigger in triggers
           if i % trigger[1] == 0
               triggered = true
               print(trigger[2])
           end
       end
       !triggered && print(i)
       println()
   end

end

print("Enter upper limit:\n> ") upper = parse(Int, readline())

triggers = Tuple{Int, ASCIIString}[] print("Enter factor/string pairs (space delimited; ^D when done):\n> ") while (r = readline()) != ""

   input = split(r)
   push!(triggers, (parse(Int, input[1]), input[2]))
   print("> ")

end

println("EOF\n") fizzbuzz(triggers, upper)</lang>

Output:
Enter upper limit:
> 20
Enter factor/string pairs (space delimited; ^D when done):
> 3 Fizz
> 5 Buzz
> 7 Baxx
> EOF

1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Kotlin

<lang Kotlin>fun main(args: Array<String>) {

   //Read the maximum number, set to 0 if it couldn't be read
   val max = readLine()?.toInt() ?: 0
   val words = mutableMapOf<Int, String>()
   //Read input three times for a factor and a word
   (1..3).forEach {
       readLine()?.let {
           val tokens = it.split(' ')
           words.put(tokens[0].toInt(), tokens[1])
       }
   }
   //Sort the words so they will be output in arithmetic order
   val sortedWords = words.toSortedMap()
   //Find the words with matching factors and print them, print the number if no factors match
   for (i in 1..max) {
       val wordsToPrint = sortedWords.filter { i % it.key == 0 }.map { it.value }
       if (wordsToPrint.isNotEmpty()) {
           wordsToPrint.forEach { print(it) }
           println()
       }
       else
           println(i)
   }

}</lang>

LiveCode

<lang LiveCode>function generalisedFizzBuzz m, f1, f2, f3

   put f1 & cr & f2 & cr & f3 into factors
   sort factors ascending numeric
   repeat with i = 1 to m
       put false into flag
       if i mod (word 1 of line 1 of factors) = 0 then
           put word 2 of line 1 of factors after fizzbuzz
           put true into flag
       end if
       if i mod (word 1 of line 2 of factors) = 0 then
           put word 2 of line 2 of factors after fizzbuzz
           put true into flag
       end if
       if i mod (word 1 of line 3 of factors) = 0 then
           put word 2 of line 3 of factors after fizzbuzz
           put true into flag
       end if
       if flag is false then put i after fizzbuzz
       put cr after fizzbuzz
   end repeat
   return fizzbuzz

end generalisedFizzBuzz</lang>Example<lang LiveCode>put generalisedFizzBuzz(20,"7 baxx","3 fizz","5 buzz")</lang>

Lua

<lang Lua>function genFizz (param)

 local response
 print("\n")
 for n = 1, param.limit do
   response = ""
   for i = 1, 3 do
     if n % param.factor[i] == 0 then
       response = response .. param.word[i]
     end
   end
   if response == "" then print(n) else print(response) end
 end

end

local param = {factor = {}, word = {}} param.limit = io.read() for i = 1, 3 do

 param.factor[i], param.word[i] = io.read("*number", "*line")

end genFizz(param)</lang>

Without modulo

Translation of: Python

<lang Lua>local function fizzbuzz(n, mods)

 local res = {}
 for i = 1, #mods, 2 do
   local mod, name = mods[i], mods[i+1]
   for i = mod, n, mod do
     res[i] = (res[i] or ) .. name
   end
 end
 for i = 1, n do
   res[i] = res[i] or i
 end
 return table.concat(res, '\n')

end

do

 local n = tonumber(io.read())     -- number of lines, eg. 100
 local mods = {}
 local n_mods = 0
 while n_mods ~= 3 do              -- for reading until EOF, change 3 to -1
   local line = io.read()
   if not line then break end
   local s, e = line:find(' ')
   local num  = tonumber(line:sub(1, s-1))
   local name = line:sub(e+1)
   mods[#mods+1] = num
   mods[#mods+1] = name
   n_mods = n_mods + 1
 end
 print(fizzbuzz(n, mods))

end </lang>

Output:
> mods = {
>>   3, 'cheese ',
>>   2, 'broccoli ',
>>   3, 'sauce ',
>> }
> fizzbuzz(8, mods)
1
broccoli 
cheese sauce 
broccoli 
5
cheese broccoli sauce 
7
broccoli 

Fast Version without Modulo

<lang lua>

  1. !/usr/bin/env luajit

local to=arg[1] or tonumber(arg[1]) or 110 local t={ {3, "Fizz"}, {5, "Buzz"}, {7, "Gazz"}, } local cnt=setmetatable({},{__index=function() return 0 end}) for i=1,to do for i=1,#t do cnt[i]=cnt[i]+1 end local match=false for i=1,#t do if cnt[i]==t[i][1] then io.write(t[i][2]) cnt[i]=0 match=true end end if not match then io.write(i) end io.write(", ") end </lang>

Output:
> ./fizzbuzz_gen.lua    
1, 2, Fizz, 4, Buzz, Fizz, Gazz, 8, Fizz, Buzz, 11, Fizz, 13, Gazz, FizzBuzz, 16, 17, Fizz, 19, Buzz, FizzGazz, 22, 23, Fizz, Buzz, 26, Fizz, Gazz, 29, FizzBuzz, 31, 32, Fizz, 34, BuzzGazz, Fizz, 37, 38, Fizz, Buzz, 41, FizzGazz, 43, 44, FizzBuzz, 46, 47, Fizz, Gazz, Buzz, Fizz, 52, 53, Fizz, Buzz, Gazz, Fizz, 58, 59, FizzBuzz, 61, 62, FizzGazz, 64, Buzz, Fizz, 67, 68, Fizz, BuzzGazz, 71, Fizz, 73, 74, FizzBuzz, 76, Gazz, Fizz, 79, Buzz, Fizz, 82, 83, FizzGazz, Buzz, 86, Fizz, 88, 89, FizzBuzz, Gazz, 92, Fizz, 94, Buzz, Fizz, 97, Gazz, Fizz, Buzz, 101, Fizz, 103, 104, FizzBuzzGazz, 106, 107, Fizz, 109, Buzz,

Maple

<lang Maple>findNum := proc(str) #help parse input local i; i := 1: while (true) do if (StringTools:-IsAlpha(str[i])) then return i-2: end if: i := i+1: end do: end proc: path := "input.txt"; input := readline(path): T := table(): maxnum := parse(input): while (true) do input := readline(path): if input = 0 then break; end if: pos := findNum(input): num := parse(input[..pos]): T[num] := input[pos+2..]: end do: for i from 1 to maxnum do factored := false: for j in [indices(T)] do if i mod j[1] = 0 then factored := true: printf(T[j[1]]); end if: end do: if (not factored) then printf("%d", i): end if: printf("\n"); end do:</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Mathematica/Wolfram Language

<lang Mathematica>list={{5,"Buzz"},{3,"Fizz"},{7,"Baxx"}}; runTo=(*LCM@@listAll,1+1*)20; Column@Table[

Select[list,Mod[x,#1]==0&]All,2/.{}->{x}
,{x,1,runTo}

]</lang>

1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Modula-2

<lang modula2>MODULE GeneralFizzBuzz; FROM Conversions IMPORT StrToInt; FROM FormatString IMPORT FormatString; FROM Terminal IMPORT Write,WriteString,WriteLn,ReadChar;

TYPE

   Word = ARRAY[0..63] OF CHAR;

PROCEDURE WriteInt(i : INTEGER); VAR buf : Word; BEGIN

   FormatString("%i", buf, i);
   WriteString(buf);

END WriteInt;

PROCEDURE ReadInt() : INTEGER; VAR

   buf : ARRAY[0..9] OF CHAR;
   c : CHAR;
   i : INTEGER;

BEGIN

   i := 0;
   LOOP
       c := ReadChar();
       IF (c=0C) OR (i>9) THEN
           BREAK
       ELSIF (c=012C) OR (c=015C) THEN
           WriteLn;
           buf[i] := 0C;
           BREAK
       ELSIF (c<'0') OR (c>'9') THEN
           Write(c);
           buf[i] := 0C;
           BREAK
       ELSE
           Write(c);
           buf[i] := c;
           INC(i)
       END
   END;
   StrToInt(buf, i);
   RETURN i

END ReadInt;

PROCEDURE ReadLine() : Word; VAR

   buf : Word;
   i : INTEGER;
   c : CHAR;

BEGIN

   i := 0;
   WHILE i<HIGH(buf) DO
       c := ReadChar();
       IF (c=0C) OR (c=012C) OR (c=015C) THEN
           WriteLn;
           buf[i] := 0C;
           BREAK
       ELSE
           Write(c);
           buf[i] := c;
           INC(i)
       END
   END;
   RETURN buf;

END ReadLine;

VAR

   i,max : INTEGER;
   fa,fb,fc : INTEGER;
   wa,wb,wc : Word;
   done : BOOLEAN;

BEGIN

   max := ReadInt();
   fa := ReadInt();
   wa := ReadLine();
   fb := ReadInt();
   wb := ReadLine();
   fc := ReadInt();
   wc := ReadLine();
   FOR i:=1 TO max DO
       done := FALSE;
       IF i MOD fa = 0 THEN
           done := TRUE;
           WriteString(wa);
       END;
       IF i MOD fb = 0 THEN
           done := TRUE;
           WriteString(wb);
       END;
       IF i MOD fc = 0 THEN
           done := TRUE;
           WriteString(wc);
       END;
       IF NOT done THEN
           WriteInt(i)
       END;
       WriteLn;
   END;
   ReadChar

END GeneralFizzBuzz.</lang>

Nanoquery

Translation of: Ursa

<lang Nanoquery>factors = {} words = {}

// get the max number print ">" max = int(input())

// get the factors inp = " " while inp != "" print ">" inp = input() if " " in inp factors.append(int(split(inp, " ")[0])) words.append(split(inp, " ")[1]) end end

// output all the numbers for i in range(1, max) foundfactor = false for j in range(0, len(factors) - 1) if (i % factors[j]) = 0 foundfactor = true print words[j] end end j = 0

if !foundfactor print i end println end</lang>

Output:
>20
>3 Fizz
>5 Buzz
>7 Baxx
>
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Nim

This solution has no input validation <lang nim> import parseutils, strutils, algorithm

type FactorAndWord = tuple[factor:int, word: string]

var number: int var factorAndWords: array[3, FactorAndWord]

  1. custom comparison proc for the FactorAndWord type

proc customCmp(x,y: FactorAndWord): int =

 if x.factor < y.factor:
   -1
 elif x.factor > y.factor:
   1
 else:
   0

echo "Enter max number:" var input = readLine(stdin) discard parseInt(input, number)

for i in 0..2:

 echo "Enter a number and word separated by space:"
 var input = readLine(stdin)
 var tokens = input.split
 discard parseInt(tokens[0], factorAndWords[i].factor)
 factorAndWords[i].word = tokens[1]
  1. sort factors in ascending order

sort(factorAndWords, customCmp)

  1. implement fiz buz

for i in 1..number:

 var written = false;
 for item in items(factorAndWords):
   if i mod item.factor == 0 :
     write(stdout, item.word)
     written = true
 if written :
   write(stdout, "\n")
 else :
   writeLine(stdout, i)


</lang>

OCaml

Original version by User:Vanyamil <lang OCaml> (* Task : General_FizzBuzz *)

(* The FizzBuzz problem, but generalized to have any strings, at any steps, up to any number of iterations.

  • )

let gen_fizz_buzz (n : int) (l : (int * string) list) : unit =

 let fold_f i (acc : bool) (k, s) = 
   if i mod k = 0
   then (print_string s; true)
   else acc
 in
 let rec helper i = 
   if i > n 
   then () 
   else
     let any_printed = List.fold_left (fold_f i) false l in
     begin
       (if not any_printed 
        then print_int i);
       print_newline ();
       helper (succ i)
     end
 in
 helper 1

(*** Output ***)

gen_fizz_buzz 20 [(3, "Fizz"); (5, "Buzz"); (7, "Baxx")] ;; </lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

PARI/GP

Works with: PARI/GP version 2.8.0+

This version uses a variadic argument to allow more or less than 3 factors. It could be easily modified for earlier versions, either by taking a vector rather than bare arguments (making the call fizz(20,[[3,"Fizz"],[5,"Buzz"],[7,"Baxx"]])) or to support exactly factors (keeping the call the same). <lang parigp>fizz(n,v[..])= { v=vecsort(v,1); for(k=1,n, my(t); for(i=1,#v, if(k%v[i][1]==0, print1(v[i][2]); t=1 ) ); print(if(t,"",k)) ); } fizz(20,[3,"Fizz"],[5,"Buzz"],[7,"Baxx"])</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Perl

<lang perl>

  1. !bin/usr/perl

use 5.020; use strict; use warnings;

  1. Get a max number from the user

say("Please enter the maximum possible multiple. "); my $max = <STDIN>;

  1. Get the factors from the user

my @factors = (); my $buffer; say("Now enter the first factor and its associated word. Ex: 3 Fizz "); chomp($buffer = <STDIN>); push @factors, $buffer; say("Now enter the second factor and its associated word. Ex: 5 Buzz "); chomp($buffer = <STDIN>); push @factors, $buffer; say("Now enter the third factor and its associated word. Ex: 7 Baxx "); chomp($buffer = <STDIN>); push @factors, $buffer;

  1. Counting from 1 to max

for(my $i = 1; $i <= $max; $i++) {

   #Create a secondary buffer as well as set the original buffer to the current index
   my $oBuffer;
   $buffer = $i;
   #Run through each element in our array
   foreach my $element (@factors)
   {
       #Look for white space
       $element =~ /\s/;
       #If the int is a factor of max, append it to oBuffer as a string to be printed
       if($i % substr($element, 0, @-) == 0)
       {
           $oBuffer = $oBuffer . substr($element, @+ + 1, length($element));
           #This is essentially setting a flag saying that at least one element is a factor
           $buffer = "";
       }
   }
   #If there are any factors for that number, print their words. If not, print the number.
   if(length($buffer) > 0)
   {
       print($buffer . "\n");
   }
   else
   {
       print($oBuffer . "\n");
   }

} </lang>

Output:
Please enter the maximum possible multiple. 
20
Now enter the first factor and its associated word. Ex: 3 Fizz 
3 Fizz
Now enter the second factor and its associated word. Ex: 5 Buzz 
5 Buzz
Now enter the third factor and its associated word. Ex: 7 Baxx 
7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Phix

procedure general_fizz_buzz(integer lim, sequence words, facts)
    for i=1 to lim do
        string word = ""
        for j=1 to length(facts) do
            if remainder(i,facts[j])=0 then
                word &= words[j]
            end if
        end for
        if length(word)=0 then
            word = sprintf("%d",i)
        end if
        printf(1,"%s\n",{word})
    end for
end procedure
general_fizz_buzz(20, {"Fizz","Buzz","Baxx"}, {3,5,7})
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

PHP

<lang PHP><?php

$max = 20; $factor = array(3 => 'Fizz', 5 => 'Buzz', 7 => 'Jazz');

for ($i = 1 ; $i <= $max ; $i++) {

   $matched = false;
   foreach ($factor AS $number => $word) {
       if ($i % $number == 0) {
           echo $word;
           $matched = true;
       }
   }
   echo ($matched ?  : $i), PHP_EOL;

}

?></lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Jazz
8
Fizz
Buzz
11
Fizz
13
Jazz
FizzBuzz
16
17
Fizz
19
Buzz

PicoLisp

<lang PicoLisp>(de general (N Lst)

  (for A N
     (prinl
        (or
           (extract
              '((L)
                 (and (=0 (% A (car L))) (cdr L)) )
              Lst )
           A ) ) ) )

(general 20 '((3 . Fizz) (5 . Buzz) (7 . Baxx)))</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

PowerShell

<lang powershell>$limit = 20 $data = @("3 Fizz","5 Buzz","7 Baxx") #An array with whitespace as the delimiter #Between the factor and the word

for ($i = 1;$i -le $limit;$i++){ $outP = "" foreach ($x in $data){ $data_split = $x -split " " #Split the "<factor> <word>" if (($i % $data_split[0]) -eq 0){ $outP += $data_split[1] #Append the <word> to outP } } if(!$outP){ #Is outP equal to NUL? Write-HoSt $i } else { Write-HoSt $outP } }</lang>

Output:
PS> ./GENFB
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz
PS>

Prolog

Assuming the user specifies as input two facts of the form: <lang prolog>maxNumber(105). factors([(3, "Fizz"), (5, "Buzz"), (7, "Baxx")]).</lang>

A simple Prolog solution to the generalised FizzBuzz problem is as follows:

<lang prolog>go :- maxNumber(M), factors(Fs), MLast is M+1, loop(1,MLast,Fs).

loop(B,B,_). loop(A,B,Fs) :-

   A < B, fizzbuzz(A,Fs,S), ( (S = "", Res is A) ; Res = S ), writeln(Res), 
   Next is A+1, loop(Next,B,Fs).

fizzbuzz(_,[],""). fizzbuzz(N,[(F,S)|Fs],Res) :-

   fizzbuzz(N,Fs,OldRes),
   ( N mod F =:= 0, string_concat(S,OldRes,Res) ; Res = OldRes ).</lang>

The program can be launched by querying the predicate <lang prolog>?- go.</lang>

It is worth noting that <lang prolog>factors([(3, "Fizz"), (5, "Buzz")]).</lang> corresponds to basic FizzBuzz and that the proposed solution can handle an arbitrary number of factors.

Python

Elegant naive version

<lang python>def genfizzbuzz(factorwords, numbers):

   factorwords.sort(key=lambda p: p[0])
   lines = []
   for num in numbers:
       words = .join(wrd for fact, wrd in factorwords if (num % fact) == 0)
       lines.append(words if words else str(num))
   return '\n'.join(lines)

if __name__ == '__main__':

   print(genfizzbuzz([(5, 'Buzz'), (3, 'Fizz'), (7, 'Baxx')], range(1, 21)))</lang>
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Unelegant naive version

First contribution to rosettacode, uses list comprehension to join the lists and args to allow for arbitrary range <lang python>def genfizzbuzz(numberlist, wordlist, *args):

   nml = [[numberlist[i], wordlist[i]] for i in range(len(numberlist))]
   for z in range(*args):
       res = ""
       for j in nml:
           if z % j[0] == 0:
               res += j[1]
       print(res or z)


genfizzbuzz([3, 5, 7], ['Fizz', 'Buzz', 'Baxx'], 1, 21) </lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

One liner using generator expressions

<lang python>n = 20 mappings = {3: "Fizz", 5: "Buzz", 7: "Baxx"} for i in range(1, n+1): print(.join(word*(i%key==0) for key, word in mappings.items()) or i) </lang>


Generator using counters instead of modulo

Works with: Python version 3.x

<lang Python>from collections import defaultdict

n = 100 mods = {

   3: "Fizz",
   5: "Buzz",

}

def fizzbuzz(n=n, mods=mods):

   factors = defaultdict(list)
   for mod in mods:
       factors[mod].append(mod)
   for i in range(1,n+1):
       res = 
       for mod in sorted(factors.pop(i)):
           factors[i+mod].append(mod)
           res += mods[mod]
       yield res or str(i)

if __name__ == '__main__':

   n = int(input())
   mods = { int(k): v for k,v in (input().split(maxsplit=1) for _ in range(3)) }
   for line in fizzbuzz(n, mods):
       print(line)

</lang>

Sieve of Eratosthenes

This variant uses ranges with step 3, 5, etc. Preserves order and duplicate moduli. <lang Python>from collections import defaultdict

n = 100 mods = [

   (3, 'Fizz'),
   (5, 'Buzz'),

]

def fizzbuzz(n=n, mods=mods):

   res = defaultdict(str)
   for num, name in mods:
       for i in range(num, n+1, num):
           res[i] += name
   return '\n'.join(res[i] or str(i) for i in range(1, n+1))


if __name__ == '__main__':

   n = int(input())
   mods = []
   while len(mods) != 3:   # for reading until EOF change 3 to -1
       try:
           line = input()
       except EOFError:
           break
       idx = line.find(' ')                        # preserves whitespace
       num, name = int(line[:idx]), line[idx+1:]   #   after the first space
       mods.append((num, name))    # preserves order and duplicate moduli
   print(fizzbuzz(n, mods))

</lang>

Output:
>>> mods = [
...   (4, 'Four '),
...   (6, 'six '),
...   (2, 'Two '),
...   (8, 'eight... '),
...   (6, 'HA! SIX!'),
... ]
>>> print(fizzbuzz(16, mods))
1
Two 
3
Four Two 
5
six Two HA! SIX!
7
Four Two eight... 
9
Two 
11
Four six Two HA! SIX!
13
Two 
15
Four Two eight... 

R

... solution

The task asks that we assume 3 factors for the sake of simplicity. However, R makes the k factors case not much more complicated, so we will do that. The only major downside is that checking for malformed user input becomes so difficult that we will not bother. <lang r>genFizzBuzz <- function(n, ...) {

 args <- list(...)
 #R doesn't like vectors of mixed types, so c(3, "Fizz") is coerced to c("3", "Fizz"). We must undo this.
 #Treating "[[" as if it is a function is a bit of R's magic. You can treat it like a function because it actually is one.
 factors <- as.integer(sapply(args, "[[", 1)) 
 words <- sapply(args, "[[", 2)
 sortedPermutation <- sort.list(factors)#Required by the task: We must go from least factor to greatest.
 factors <- factors[sortedPermutation]
 words <- words[sortedPermutation]
 for(i in 1:n)
 {
   isFactor <- i %% factors == 0
   print(if(any(isFactor)) paste0(words[isFactor], collapse = "") else i)
 }

} genFizzBuzz(105, c(3, "Fizz"), c(5, "Buzz"), c(7, "Baxx")) genFizzBuzz(105, c(5, "Buzz"), c(9, "Prax"), c(3, "Fizz"), c(7, "Baxx"))</lang>

Names solution

If we deviate from the task's example of how to input parameters and instead use R's names facilities to make our (number, name) pairs, we get a much cleaner solution. <lang r>namedGenFizzBuzz <- function(n, namedNums) {

 factors <- sort(namedNums)#Required by the task: We must go from least factor to greatest.
 for(i in 1:n)
 {
   isFactor <- i %% factors == 0
   print(if(any(isFactor)) paste0(names(factors)[isFactor], collapse = "") else i)
 }

} namedNums <- c(Fizz=3, Buzz=5, Baxx=7)#Notice that we can name our inputs without a function call. namedGenFizzBuzz(105, namedNums) shuffledNamedNums <- c(Buzz=5, Prax=9, Fizz=3, Baxx=7) namedGenFizzBuzz(105, shuffledNamedNums)</lang>

Racket

Translation of: Python

<lang Racket>#lang racket/base

(define (get-matches num factors/words)

 (for*/list ([factor/word (in-list factors/words)]
             [factor (in-value (car factor/word))]
             [word (in-value (cadr factor/word))] 
             #:when (zero? (remainder num factor)))
   word))

(define (gen-fizzbuzz from to factors/words)

 (for ([num (in-range from to)])
   (define matches (get-matches num factors/words))
   (displayln (if (null? matches)
                 (number->string num)
                 (apply string-append matches)))))

(gen-fizzbuzz 1 21 '((3 "Fizz")

                    (5 "Buzz")
                    (7 "Baxx")))</lang>
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Alternate Solution

<lang Racket>#lang racket (require racket/match)

(define (fizz-buzz-individual x . args)

 (match (string-append*
         (map (lambda (i)
                (match i
                  [(cons a b) (if (= 0 (modulo x a)) b "")])) args))
   ["" x]
   [fizz-buzz-string fizz-buzz-string]))

(define (fizz-buzz x . args)

 (map (curryr (compose displayln (curry apply fizz-buzz-individual)) args)
      (range 1 (add1 x)))
 (void))

(fizz-buzz 20 '(3 . "Fizz") '(5 . "Buzz") '(7 . "Baxx"))</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Raku

(formerly Perl 6)

Works with: rakudo version 2015-09-20

<lang perl6># General case implementation of a "FizzBuzz" class.

  1. Defaults to standard FizzBuzz unless a new schema is passed in.

class FizzBuzz {

   has $.schema is rw = < 3 Fizz 5 Buzz >.hash;
   method filter (Int $this) {
       my $fb;
       for $.schema.sort: { +.key } -> $p { $fb ~= $this %% +$p.key ?? $p.value !! };
       return $fb || $this;
   }

}


  1. Sub implementing the specific requirements of the task.

sub GeneralFizzBuzz (Int $upto, @schema?) {

   my $ping = FizzBuzz.new;
   $ping.schema = @schema.hash if @schema;
   map { $ping.filter: $_ }, 1 .. $upto;

}

  1. The task

say 'Using: 20 ' ~ <3 Fizz 5 Buzz 7 Baxx>; .say for GeneralFizzBuzz(20, <3 Fizz 5 Buzz 7 Baxx>);

say ;

  1. And for fun

say 'Using: 21 ' ~ <2 Pip 4 Squack 5 Pocketa 7 Queep>; say join ', ', GeneralFizzBuzz(21, <2 Pip 4 Squack 5 Pocketa 7 Queep>);</lang>

Output:
Using: 20 3 Fizz 5 Buzz 7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Using: 21 2 Pip 4 Squack 5 Pocketa 7 Queep
1, Pip, 3, PipSquack, Pocketa, Pip, Queep, PipSquack, 9, PipPocketa, 11, PipSquack, 13, PipQueep, Pocketa, PipSquack, 17, Pip, 19, PipSquackPocketa, Queep

Here's the same program in a more functional idiom: <lang perl6>sub genfizzbuzz($n, +@fb) {

   [Z~](
       do for @fb || <3 fizz 5 buzz> -> $i, $s {
           flat ( xx $i-1, $s) xx *;
       }
   ) Z|| 1..$n

}

.say for genfizzbuzz(20, <3 Fizz 5 Buzz 7 Baxx>);</lang>

Red

<lang Red>Red ["FizzBuzz"]

nmax: to-integer ask "Max number: " while ["" <> trim rule: ask "New rule (empty to end): "][ append rules: [] load rule ] repeat n nmax [ res: copy "" foreach [x blah] rules [ if n % x = 0 [append res blah] ] print either empty? res [n] [res] ] halt</lang>

Output:
Max number: 21
New rule (empty to end): 3 Fizz
New rule (empty to end): 5 Buzz
New rule (empty to end): 7 Baxx
New rule (empty to end): 
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz
FizzBaxx
(halted)

REXX

idiomatic version

<lang rexx>/*REXX program shows a generalized FizzBuzz program: #1 name1 #2 name2 ··· */ parse arg h $ /*obtain optional arguments from the CL*/ if h= | h="," then h= 20 /*Not specified? Then use the default.*/ if $= | $="," then $= "3 Fizz 5 Buzz 7 Baxx" /* " " " " " " */ factors= words($) % 2 /*determine number of factors to use. */

 do i=1  by 2  for factors                      /*parse the number factors to be used. */
 #.i=word($, i);   @.i=word($, i+1)             /*obtain the factor and its  "name".   */
 end   /*i*/
 do j=1  for h;                    z=           /*traipse through the numbers to   H.  */
                 do k=1  by 2  for factors      /*   "       "     " factors  in   J.  */
                 if j//#.k==0  then z= z || @.k /*Is it a factor?  Then append it to Z.*/
                 end   /*k*/                    /* [↑]  Note:  the factors may be zero.*/
 say word(z j, 1)                               /*display the number  or  its factors. */
 end                  /*j*/                     /*stick a fork in it,  we're all done. */</lang>
output   when using the default input:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

optimized version

<lang rexx>/*REXX program shows a generalized FizzBuzz program: #1 name1 #2 name2 ··· */ parse arg h $ /*obtain optional arguments from the CL*/ if h= | h="," then h= 20 /*Not specified? Then use the default.*/ if $= | $="," then $= "3 Fizz 5 Buzz 7 Baxx" /* " " " " " " */

 do j=1  for h;             z=                  /*traipse through the numbers to   H.  */
   do k=1  by 2  for words($)%2                 /*   "       "     " factors  in   J.  */
   if j//word($,k)==0  then z= z || word($,k+1) /*Is it a factor?  Then append it to Z.*/
   end   /*k*/                                  /* [↑]  Note:  the factors may be zero.*/
 say word(Z j, 1)                               /*display the number  or  its factors. */
 end     /*j*/                                  /*stick a fork in it,  we're all done. */</lang>
output   is identical to the 1st REXX version.


Ring

<lang ring> limit = 20 for n = 1 to limit

   if n % 3 = 0 see "" + n + " = " + "Fizz"+ nl
   but n % 5 = 0 see "" + n + " = " + "Buzz" + nl
   but n % 7 = 0 see "" + n + " = " + "Baxx" + nl
   else see "" + n + " = " + n + nl ok

next

</lang>

Ruby

<lang ruby>def general_fizzbuzz(text)

 num, *nword = text.split
 num = num.to_i
 dict = nword.each_slice(2).map{|n,word| [n.to_i,word]}
 (1..num).each do |i|
   str = dict.map{|n,word| word if i%n==0}.join
   puts str.empty? ? i : str
 end

end

text = <<EOS 20 3 Fizz 5 Buzz 7 Baxx EOS

general_fizzbuzz(text)</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Rust

<lang rust>use std::io; use std::io::BufRead;

fn parse_entry(l: &str) -> (i32, String) {

   let params: Vec<&str> = l.split(' ').collect();
   let divisor = params[0].parse::<i32>().unwrap();
   let word = params[1].to_string();
   (divisor, word)

}

fn main() {

   let stdin = io::stdin();
   let mut lines = stdin.lock().lines().map(|l| l.unwrap());
   let l = lines.next().unwrap();
   let high = l.parse::<i32>().unwrap();
   let mut entries = Vec::new();
   for l in lines {
       if &l == "" { break }
       let entry = parse_entry(&l);
       entries.push(entry);
   }
   for i in 1..(high + 1) {
       let mut line = String::new();
       for &(divisor, ref word) in &entries {
           if i % divisor == 0 {
               line = line + &word;
           }
       }
       if line == "" {
           println!("{}", i);
       } else {
           println!("{}", line);
       }
   }

}</lang>

This solution stores the Fizz Buzz state in a struct, leveraging types and the standard library for a more general solution:

<lang rust>use std::collections::BTreeMap; use std::fmt::{self, Write}; use std::io::{self, Stdin};

  1. [derive(Debug, PartialEq)]

pub struct FizzBuzz {

   end: usize,
   factors: Factors,

}

impl FizzBuzz {

   fn from_reader(rdr: &Stdin) -> Result<FizzBuzz, Box<dyn std::error::Error>> {
       let mut line = String::new();
       rdr.read_line(&mut line)?;
       let end = line.trim().parse::<usize>()?;
       let mut factors = Factors::new();
       loop {
           let mut line = String::new();
           rdr.read_line(&mut line)?;
           if line.trim().is_empty() { break; }
           let mut split = line.trim().splitn(2, ' ');
           let factor = match split.next() {
               Some(f) => f.parse::<usize>()?,
               None => break,
           };
           let phrase = match split.next() {
               Some(p) => p,
               None => break,
           };
           factors.insert(factor, phrase.to_string());
       }
       Ok(FizzBuzz { end, factors })
   }

}

impl fmt::Display for FizzBuzz {

   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       for n in 1..=self.end {
           let mut had_factor = false;
           // check for factors
           for (factor, phrase) in self.factors.iter() {
               if n % factor == 0 {
                   f.write_str(&phrase)?;
                   had_factor = true;
               }
           }
           if !had_factor {
               f.write_str(n.to_string().as_str())?;
           }
           f.write_char('\n')?;
       }
       Ok(())
   }

}

type Factors = BTreeMap<usize, String>;

fn main() -> Result<(), Box<dyn std::error::Error>> {

   let input = io::stdin();
   let fizz_buzz = FizzBuzz::from_reader(&input)?;
   println!("{}", fizz_buzz);
   Ok(())

}

  1. [cfg(test)]

mod tests {

   use super::*;
   #[test]
   fn fizz_buzz_prints_expected_format() {
       let expected_factors = {
           let mut map = Factors::new();
           map.insert(3, "Fizz".to_string());
           map.insert(5, "Buzz".to_string());
           map.insert(7, "Baxx".to_string());
           map
       };
       let expected_end = 20;
       let fizz_buzz = FizzBuzz {
           end: expected_end,
           factors: expected_factors,
       };
       let expected = r#"1

2 Fizz 4 Buzz Fizz Baxx 8 Fizz Buzz 11 Fizz 13 Baxx FizzBuzz 16 17 Fizz 19 Buzz "#;

       let printed = format!("{}", fizz_buzz);
       assert_eq!(expected, &printed);
   }

}</lang>

Scala

Output for all examples:
$ scala GeneralFizzBuzz.scala
20
3 Fizz
5 Buzz
7 Baxx
^D

1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Simple

<lang Scala>import scala.io.{Source, StdIn}

object GeneralFizzBuzz extends App {

 val max = StdIn.readInt()
 val factors = Source.stdin.getLines().toSeq
   .map(_.split(" ", 2))
   .map(f => f(0).toInt -> f(1))
   .sorted
 (1 to max).foreach { i =>
   val words = factors.collect { case (k, v) if i % k == 0 => v }
   println(if (words.nonEmpty) words.mkString else i)
 }

}</lang>

LazyList (f/k/a Stream)

<lang Scala>import scala.io.{Source, StdIn}

object GeneralFizzBuzz extends App {

 def fizzBuzzTerm(n: Int, factors: Seq[(Int, String)]): String = {
   val words = factors.collect { case (k, v) if n % k == 0 => v }
   if (words.nonEmpty) words.mkString else n.toString
 }
 def fizzBuzz(factors: Seq[(Int, String)]): LazyList[String] =
   LazyList.from(1).map(fizzBuzzTerm(_, factors))
 val max = StdIn.readInt()
 val factors = Source.stdin.getLines().toSeq
   .map(_.split(" ", 2))
   .map { case Array(k, v) => k.toInt -> v }
   .sorted
 fizzBuzz(factors).take(max).foreach(println)

}</lang>

Scala 3 (Dotty)

Translation of: LazyList (f/k/a Stream)

<lang Scala>import scala.io.{Source, StdIn}

def fizzBuzzTerm(n: Int, factors: Seq[(Int, String)]): String | Int =

 val words = factors.collect { case (k, v) if n % k == 0 => v }
 if words.nonEmpty then words.mkString else n

def fizzBuzz(factors: Seq[(Int, String)]): LazyList[String | Int] =

 LazyList.from(1).map(i => fizzBuzzTerm(i, factors))

@main def run(): Unit =

 val max = StdIn.readInt()
 val factors: Seq[(Int, String)] = Source.stdin.getLines().toSeq
   .map(_.split(" ", 2))
   .map { case Array(k, v) => k.toInt -> v }
   .sorted
 fizzBuzz(factors).take(max).foreach(println)</lang>

Sidef

<lang ruby>class FizzBuzz(schema=Hash(<3 Fizz 5 Buzz>...)) {

   method filter(this) {
       var fb = 
       schema.sort_by {|k,_| k.to_i }.each { |pair|
           fb += (pair[0].to_i `divides` this ? pair[1] : )
       }
       fb.len > 0 ? fb : this
   }

}   func GeneralFizzBuzz(upto, schema) {

   var ping = FizzBuzz()
   if (nil != schema) {
       ping.schema = schema.to_hash
   }
   (1..upto).map {|i| ping.filter(i) }

}   GeneralFizzBuzz(20, <3 Fizz 5 Buzz 7 Baxx>).each { .say }</lang>

Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Tailspin

<lang tailspin> def input: {N: 110, words: [ { mod: 3, word: 'Fizz' }, { mod: 5, word: 'Buzz'}, {mod:7, word: 'Baxx'}]};

templates sayWords

 def i: $;
 templates maybeSay
   def word: $.word;
   $i mod $.mod -> \(<=0> $word !\) !
 end maybeSay
 $input.words... -> maybeSay !

end sayWords

[ 1..$input.N -> '$->sayWords;' ] -> \[i](<> $i ! <> $ !\) -> '$; ' -> !OUT::write </lang>

Output:
[1, 2, Fizz, 4, Buzz, Fizz, Baxx, 8, Fizz, Buzz, 11, Fizz, 13, Baxx, FizzBuzz, 16, 17, Fizz, 19, Buzz, FizzBaxx, 22, 23, Fizz, Buzz, 26, Fizz, Baxx, 29, FizzBuzz, 31, 32, Fizz, 34, BuzzBaxx, Fizz, 37, 38, Fizz, Buzz, 41, FizzBaxx, 43, 44, FizzBuzz, 46, 47, Fizz, Baxx, Buzz, Fizz, 52, 53, Fizz, Buzz, Baxx, Fizz, 58, 59, FizzBuzz, 61, 62, FizzBaxx, 64, Buzz, Fizz, 67, 68, Fizz, BuzzBaxx, 71, Fizz, 73, 74, FizzBuzz, 76, Baxx, Fizz, 79, Buzz, Fizz, 82, 83, FizzBaxx, Buzz, 86, Fizz, 88, 89, FizzBuzz, Baxx, 92, Fizz, 94, Buzz, Fizz, 97, Baxx, Fizz, Buzz, 101, Fizz, 103, 104, FizzBuzzBaxx, 106, 107, Fizz, 109, Buzz]

Tcl

Tcl excels at metaprogramming, so this task is trivial. For fun, the below implementation is a compatible extension of FizzBuzz#Tcl:

<lang Tcl>proc fizzbuzz {n args} {

   if {$args eq ""} {
       set args {{3 Fizz} {5 Buzz}}
   }
   while {[incr i] <= $n} {
       set out ""
       foreach rule $args {
           lassign $rule m echo
           if {$i % $m == 0} {append out $echo}
       }
       if {$out eq ""} {set out $i}
       puts $out
   }

} fizzbuzz 20 {3 Fizz} {5 Buzz} {7 Baxx}</lang>

Ursa

This program reads a max number, then reads factors until the user enters a blank line. <lang ursa>#

  1. general fizzbuzz

decl int<> factors decl string<> words decl int max

  1. get the max number

out ">" console set max (in int console)

  1. get the factors

decl string input set input " " while (not (= input ""))

       out ">" console
       set input (in string console)
       if (not (= input ""))
               append (int (split input " ")<0>) factors
               append (split input " ")<1> words
       end if

end while

  1. output all the numbers

decl int i for (set i 1) (< i (+ max 1)) (inc i)

       decl boolean foundfactor
       set foundfactor false
       for (decl int j) (< j (size factors)) (inc j)
               if (= (mod i factors<j>) 0)
                       set foundfactor true
                       out words<j> console
               end if
       end for
       set j 0
       if (not foundfactor)
               out i console
       end if
       out endl console

end for</lang> Output:

>20
>3 Fizz
>5 Buzz
>7 Baxx
>
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

VBA

<lang vb> Option Explicit

Private Type Choice

   Number As Integer
   Name As String

End Type

Private MaxNumber As Integer

Sub Main() Dim U(1 To 3) As Choice, i As Integer, j As Integer, t$

   MaxNumber = Application.InputBox("Enter the max number : ", "Integer please", Type:=1)
   For i = 1 To 3
       U(i) = UserChoice
   Next
   For i = 1 To MaxNumber
       t = vbNullString
       For j = 1 To 3
           If i Mod U(j).Number = 0 Then t = t & U(j).Name
       Next
       Debug.Print IIf(t = vbNullString, i, t)
   Next i

End Sub

Private Function UserChoice() As Choice Dim ok As Boolean

   Do While Not ok
       UserChoice.Number = Application.InputBox("Enter the factors to be calculated : ", "Integer please", Type:=1)
       UserChoice.Name = InputBox("Enter the corresponding word : ")
       If StrPtr(UserChoice.Name) <> 0 And UserChoice.Number < MaxNumber Then ok = True
   Loop

End Function</lang>

Output:

With the entry : Max : 120; 3 : Fizz; 5 : Buzz; 7 : Baxx

 1 
 2 
Fizz
 4 
Buzz
Fizz
Baxx
 8 
Fizz
Buzz
 11 
Fizz
 13 
Baxx
FizzBuzz
 16 
 17 
Fizz
 19 
Buzz
FizzBaxx
 22 
 23 
......
Buzz
 101 
Fizz
 103 
 104 
FizzBuzzBaxx
 106 
 107 
Fizz
 109 
Buzz
Fizz
Baxx
 113 
Fizz
Buzz
 116 
Fizz
 118 
Baxx
FizzBuzz

VBScript

<lang vb>'The Function Function FizzBuzz(range, mapping)

   data = Array()
   'Parse the mapping and put to "data" array
   temp = Split(mapping, ",")
   ReDim data(UBound(temp),1)
   For i = 0 To UBound(temp)
       map = Split(temp(i), " ")
       data(i, 0) = map(0)
       data(i, 1) = map(1)
   Next    
   'Do the loop
   For i = 1 to range
       noMatch = True
       For j = 0 to UBound(data, 1)
           If (i Mod data(j, 0)) = 0 Then
               WScript.StdOut.Write data(j, 1)
               noMatch = False
           End If
       Next
       If noMatch Then WScript.StdOut.Write i
       WScript.StdOut.Write vbCrLf
   Next

End Function

'The Main Thing WScript.StdOut.Write "Range? " x = WScript.StdIn.ReadLine WScript.StdOut.Write "Mapping? " y = WScript.StdIn.ReadLine WScript.StdOut.WriteLine "" FizzBuzz x, y</lang>

Sample Run:
\Desktop>cscript /nologo fizzbuzz.vbs
Range? 20
Mapping? 3 Fizz,5 Buzz,7 Baxx

1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

\Desktop>

Visual Basic .NET

<lang vbnet>Imports System.Globalization

Module Program

   Sub Main()
       Console.Write("Max: ")
       Dim max = Integer.Parse(Console.ReadLine(), CultureInfo.InvariantCulture)
       Dim factors As New SortedDictionary(Of Integer, String)
       Const NUM_FACTORS = 3
       For i = 1 To NUM_FACTORS
           Console.Write("Factor {0}: ", i)
           Dim input = Console.ReadLine().Split()
           factors.Add(Integer.Parse(input(0), CultureInfo.InvariantCulture), input(1))
       Next
       For i = 1 To max
           Dim anyMatches = False
           For Each factor In factors
               If i Mod factor.Key = 0 Then
                   Console.Write(factor.Value)
                   anyMatches = True
               End If
           Next
           If Not anyMatches Then Console.Write(i)
           Console.WriteLine()
       Next
   End Sub

End Module</lang>

Output:
Max: 20
Factor 1: 7 Baxx
Factor 2: 3 Fizz
Factor 3: 5 Buzz
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Wren

Library: Wren-sort

<lang ecmascript>import "io" for Stdin, Stdout import "/sort" for Sort

var n

while (true) {

   System.write("Maximum number : ")
   Stdout.flush()
   n = Num.fromString(Stdin.readLine())
   if (!n || !n.isInteger || n < 3) {
       System.print("Must be an integer > 2, try again.")
   } else {
       break
   }

}

var factors = [] var words = {} for (i in 0..2) {

   while (true) {
       System.write("Factor %(i+1) : ")
       Stdout.flush()
       var factor = Num.fromString(Stdin.readLine())
       if (!factor || !factor.isInteger || factor < 2 || factors.contains(factor)) {
           System.print("Must be an unused integer > 1, try again.")
       } else {
           factors.add(factor)
           var outer = false
           while (true) {
               System.write("  Word %(i+1) : ")
               Stdout.flush()
               var word = Stdin.readLine()
               if (word.count == 0) {
                   System.print("Must have at least one character, try again.")
               } else {
                   words[factor] = word
                   outer = true
                   break
               }
           }
           if (outer) break
       }
   }

}

Sort.insertion(factors) System.print() for (i in 1..n) {

   var s = ""
   for (j in 0..2) {
       var factor = factors[j]
       if (i % factor == 0) s = s + words[factor]
   }
   if (s == "") s = i.toString
   System.print(s)

}</lang>

Output:
Maximum number : 20
Factor 1 : 3
  Word 1 : Fizz
Factor 2 : 5
  Word 2 : Buzz
Factor 3 : 7
  Word 3 : Bazz

1
2
Fizz
4
Buzz
Fizz
Bazz
8
Fizz
Buzz
11
Fizz
13
Bazz
FizzBuzz
16
17
Fizz
19
Buzz

zkl

<lang zkl>stop:=ask("Count: ").toInt(); fizzBuzzers:=List(); do(3){ n,txt:=ask(">").split(); fizzBuzzers.append(T(n.toInt(),txt)) } foreach n in ([1..stop]){

  s:=fizzBuzzers.filter('wrap([(fb,txt)]){ n%fb==0 }).apply("get",1).concat();
  println(s or n);

}</lang>

Output:
$ zkl bbb
Count: 20
>3 Fizz 
>5 Buzz
>7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

ZX Spectrum Basic

Translation of: BBC_BASIC

<lang zxbasic>10 INPUT "Maximum number: ";max 20 INPUT "Number of factors: ";n 30 DIM f(n): DIM w$(n,4) 40 FOR i=1 TO n 50 INPUT "Input value-ENTER-word: ";f(i);w$(i) 60 NEXT i 70 FOR i=1 TO max 80 LET matched=0 90 FOR j=1 TO n 100 IF FN m(i,f(j))=0 THEN LET matched=1: PRINT w$(j); 110 NEXT j 120 IF NOT matched THEN PRINT ;i: GO TO 140 130 PRINT 140 NEXT i 150 DEF FN m(a,b)=a-INT (a/b)*b</lang>