General FizzBuzz: Difference between revisions

From Rosetta Code
Line 1,830: Line 1,830:
 
*/
 
*/
 
public static void main(String[] args) {
 
public static void main(String[] args) {
 
Function<String[],Function<Integer,String>> make_cycle_function =
BiFunction<Integer,String,String> formatter = (i,printThis) -> "".equals(printThis)?Integer.toString(i):printThis;
 
 
parts -> j -> j%(Integer.parseInt(parts[0]))==0?parts[1]:"";
List<Function<Integer,String>> cycle_functions = new ArrayList<>();
 
  +
List<Function<Integer,String>> cycle_functions = Stream.of(args)
 
.map(arg -> arg.split("="))
 
.filter(parts->parts.length==2)
  +
.map(make_cycle_function::apply)
  +
.collect(Collectors.toList());
 
Function<Integer,String> moduloTesters = i -> cycle_functions.stream()
 
Function<Integer,String> moduloTesters = i -> cycle_functions.stream()
 
.map(fcn->fcn.apply(i))
 
.map(fcn->fcn.apply(i))
 
.collect(Collectors.joining());
 
.collect(Collectors.joining());
  +
BiFunction<Integer,String,String> formatter =
 
(i,printThis) -> "".equals(printThis)?Integer.toString(i):printThis;
 
Function<Integer,String> fizzBuzz = i -> formatter.apply(i,moduloTesters.apply(i));
 
Function<Integer,String> fizzBuzz = i -> formatter.apply(i,moduloTesters.apply(i));
Stream.of(args)
+
.filter(arg->arg.contains("="))
 
.forEach(arg->{
 
String[] parts = arg.split("=");
 
cycle_functions.add(j-> j%(Integer.parseInt(parts[0]))==0?parts[1]:"");
 
});
 
 
 
IntStream.rangeClosed(0,Integer.parseInt(args[args.length-1]))
 
IntStream.rangeClosed(0,Integer.parseInt(args[args.length-1]))
 
.mapToObj(Integer::valueOf)
 
.mapToObj(Integer::valueOf)

Revision as of 21:50, 24 September 2022

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
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))
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Action!

DEFINE MAX_NUMBERS="200"
DEFINE MAX_LEN="20"
DEFINE MAX_FACTORS="5"
DEFINE PTR="CARD"

PROC PrintResult(BYTE max,n BYTE ARRAY factors PTR ARRAY texts)
  BYTE i,j,t
  BYTE ARRAY values(MAX_FACTORS)

  FOR j=0 TO n-1
  DO
    values(j)=1
  OD

  FOR i=1 TO max
  DO
    t=0
    FOR j=0 TO n-1
    DO
      IF values(j)=0 THEN
        t=1 Print(texts(j))
      FI
      values(j)==+1
      IF values(j)=factors(j) THEN
        values(j)=0
      FI
    OD
    IF t=0 THEN PrintB(i) FI
    Put(32)
  OD
RETURN

BYTE FUNC Find(CHAR ARRAY s CHAR c BYTE POINTER err)
  BYTE i

  FOR i=1 TO s(0)
  DO
    IF s(i)=c THEN
      err^=0 RETURN (i)
    FI
  OD
  err^=1
RETURN (0)

PROC Main()
  BYTE max,i,n,pos,err
  BYTE ARRAY factors(MAX_FACTORS)
  PTR ARRAY texts(MAX_FACTORS)
  CHAR ARRAY
    s(100),tmp(100),
    t0(MAX_LEN),t1(MAX_LEN),t2(MAX_LEN),
    t3(MAX_LEN),t4(MAX_LEN)
  
  texts(0)=t0 texts(1)=t1 texts(2)=t2
  texts(3)=t3 texts(4)=t4

  DO
    PrintF("Max number (1-%B): ",MAX_NUMBERS)
    max=InputB()
  UNTIL max>=1 AND max<=MAX_NUMBERS
  OD

  n=0
  DO
    PrintF("Number of rules (1-%B): ",MAX_FACTORS)
    n=InputB()
  UNTIL n>=1 AND n<=MAX_FACTORS
  OD

  FOR i=0 TO n-1
  DO
    DO
      PrintF("Rule #%B (number space text):",i+1)
      InputS(s)
      pos=Find(s,' ,@err)
      IF pos=1 OR pos=s(0) THEN
        err=1
      FI
      IF err=0 THEN
        SCopyS(tmp,s,1,pos-1)
        factors(i)=ValB(tmp)
        IF factors(i)<2 THEN
          err=1
        FI
        SCopyS(texts(i),s,pos+1,s(0))
      FI
    UNTIL err=0
    OD
  OD

  PutE()
  PrintResult(max,n,factors,texts)
RETURN
Output:

Screenshot from Atari 8-bit computer

Max number (1-200): 105
Number of rules (1-5): 3
Rule #1 (number space text):3 Fizz
Rule #2 (number space text):5 Buzz
Rule #3 (number space text):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
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

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;
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.

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
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

--------------------- 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
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Arturo

maxNum: to :integer strip input "Set maximum number: "
facts: map 1..3 'x -> split.words strip input ~"Enter factor |x|: "
loop 1..maxNum 'i [
    printNum: true
    loop facts 'fact ->
        if zero? i % to :integer fact\0 [
            prints fact\1
            printNum: false
        ]
    print (printNum)? -> i -> ""
]
Output:
Set maximum number: 20
Enter factor 1: 3 Fizz
Enter factor 2: 5 Buzz
Enter factor 3: 7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

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, *
}
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
awk  -f fizzbuzzGenerate.awk  input.txt > fizzbuzzCustom.awk
awk  -f fizzbuzzCustom.awk  numbers.txt
Program
# 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." )
}

Example output see FizzBuzz/AWK#Custom_FizzBuzz

Batch File

@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
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.

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

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

BQN

GenFizzBuzz ← {factors‿words ← <˘⍉>𝕨 ⋄ (∾´∾⟜words/˜·(¬∨´)⊸∾0=factors|⊢)¨1+↕𝕩}

Example usage:

    ⟨3‿"Fizz", 5‿"Buzz", 7‿"Baxx"⟩ GenFizzBuzz 20
⟨ 1 2 "Fizz" 4 "Buzz" "Fizz" "Baxx" 8 "Fizz" "Buzz" 11 "Fizz" 13 "Baxx" "FizzBuzz" 16 17 "Fizz" 19 "Buzz" ⟩

C

#include <stdio.h>
#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;
}
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.

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();
        }
    }
}

C++

#include <algorithm>
#include <iostream>
#include <vector>
#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;
}
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

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


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

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);
		}
	}
}

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)))

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

(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))))

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

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();
        }
    }
}
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
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)
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

%%% @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)]
    ).

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

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
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 ..'

\ 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
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
' 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
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

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
	}

}

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
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

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)

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

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
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:

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

Example use:

   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

For our example, b looks like this:

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

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

   */*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

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

┌┬┬────┬┬────┬────┬────┬┬────┬────┬┬────┬┬────┬────┬┬┬────┬┬────┐
│││Fizz││    Fizz    ││Fizz    ││Fizz││    Fizz│││Fizz││    
├┼┼────┼┼────┼────┼────┼┼────┼────┼┼────┼┼────┼────┼┼┼────┼┼────┤
│││    ││Buzz        ││    Buzz││    ││    Buzz│││    ││Buzz
├┼┼────┼┼────┼────┼────┼┼────┼────┼┼────┼┼────┼────┼┼┼────┼┼────┤
│││    ││        Baxx││        ││    ││Baxx    │││    ││    
└┴┴────┴┴────┴────┴────┴┴────┴────┴┴────┴┴────┴────┴┴┴────┴┴────┘

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

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 : "";
        }

    }

}


For a more complete example see jFizzBuzz

Or using a lot of Lambdas ...

import java.util.stream.*;
import java.util.function.*;
import java.util.*;
public class fizzbuzz_general {
    /**
     * To run: java fizzbuzz_general.java 3=Fizz 5=Buzz 7=Baxx 100
     *
     */
    public static void main(String[] args) {
        Function<String[],Function<Integer,String>> make_cycle_function = 
              parts -> j -> j%(Integer.parseInt(parts[0]))==0?parts[1]:"";
        List<Function<Integer,String>> cycle_functions = Stream.of(args)
                     .map(arg -> arg.split("="))
                     .filter(parts->parts.length==2)
                     .map(make_cycle_function::apply)
                     .collect(Collectors.toList());
        Function<Integer,String> moduloTesters = i -> cycle_functions.stream()
                                   .map(fcn->fcn.apply(i))
                                   .collect(Collectors.joining());
        BiFunction<Integer,String,String> formatter = 
                    (i,printThis) -> "".equals(printThis)?Integer.toString(i):printThis;                               
        Function<Integer,String> fizzBuzz = i -> formatter.apply(i,moduloTesters.apply(i));
       
        IntStream.rangeClosed(0,Integer.parseInt(args[args.length-1]))
           .mapToObj(Integer::valueOf)
           .map(fizzBuzz::apply)
           .forEach(System.out::println);
    }
}

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:

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";
  }, "");
}

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

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);
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz


ES6

// 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))
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.

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)
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

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)
    }
}

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
Example
put generalisedFizzBuzz(20,"7 baxx","3 fizz","5 buzz")

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)

Without modulo

Translation of: Python
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
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

#!/usr/bin/env luajit

local num = arg[1] or tonumber(arg[1]) or 110
local t = {
	{3, "Fizz"},
	{5, "Buzz"},
	{7, "Gazz"},
}

-- `cnt` contains counters for each factor-word pair; when a counter of a pair reaches its factor,
-- the counter is reset to zero and the word is written to output
local cnt = setmetatable({}, {__index = function() return 0 end})

for i = 1,num 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
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

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:
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Mathematica/Wolfram Language

list={{5,"Buzz"},{3,"Fizz"},{7,"Baxx"}};
runTo=(*LCM@@list[[All,1]]+1*)20;
Column@Table[
 Select[list,Mod[x,#[[1]]]==0&][[All,2]]/.{}->{x}
 ,{x,1,runTo}
]
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

MiniScript

This implementation improves slightly over the proposed task, making the prompts a little friendlier.

factorWords = {}

maxNr = val(input("Max number? "))

while true
	factorInput = input("Factor? ")
	if factorInput == "" then break
	// Split input
	parts = factorInput.split(" ")
	factor = val(parts[0])
	word = parts[1]
	// Assign factor/word
	factorWords[factor] = word
end while

for nr in range(1,maxNr)
	matchingWords = ""
	for factor in factorWords.indexes
		if nr % factor == 0 then 
			matchingWords = matchingWords + factorWords[factor]
		end if
	end for
	if matchingWords then print matchingWords else print nr
end for

Sample session:

Max number? 20
Factor? 3 Fizz
Factor? 5 Buzz
Factor?
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz

Modula-2

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.

Nanoquery

Translation of: Ursa
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
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

import parseutils, strutils, algorithm

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

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

#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]

#sort factors in ascending order
sort(factorAndWords, customCmp)

#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)

OCaml

Original version by User:Vanyamil

(* 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")] ;;
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).

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"])
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Perl

#!bin/usr/perl
use 5.020;
use strict;
use warnings;

#Get a max number from the user
say("Please enter the maximum possible multiple. ");
my $max = <STDIN>;

#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;

#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");
    }
}
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

<?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;
}

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

Picat

interactive =>
   print("> "),
   MaxNum = read_int(),
   Map = new_map(),
   print("> "),
   while (Line = read_line(), Line != "")
     [N,V] = split(Line),
     Map.put(N.to_int,V),
     print("> ")
   end,
   general_fizzbuzz(MaxNum,Map.to_list.sort),
   nl.

general_fizzbuzz(N,L) =>
  FB = [I.to_string : I in 1..N],
  foreach(I in 1..N)
    Vs = [V : K=V in L, I mod K == 0].join(''),
    if Vs != "" then
      FB[I] := Vs
    end
  end,
  println([F : F in FB].join(" ")).

Testing:

$ echo "106\n3 Fizz\n5 Buzz\n7 Bazz\n" | picat -g interactive general_fizzbuzz.pi

Here's an interactive session:

Output:
> 106
> 3 Fizz
> 5 Buzz
> 7 Baxx
> 
1
2
Fizz
4
Buzz
Fizz
Bazz
8
Fizz
Buzz
11
Fizz
13
Bazz
FizzBuzz
16
17
Fizz
19
Buzz
FizzBazz
22
...
Bazz
Fizz
Buzz
101
Fizz
103
104
FizzBuzzBazz
106


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)))
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

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
	}
}
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:

maxNumber(105).  
factors([(3, "Fizz"), (5, "Buzz"), (7, "Baxx")]).

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

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 ).

The program can be launched by querying the predicate

?- go.

It is worth noting that

factors([(3, "Fizz"), (5, "Buzz")]).

corresponds to basic FizzBuzz and that the proposed solution can handle an arbitrary number of factors.

Python

Elegant naive version

def genfizzbuzz(factorwords, numbers):
    # sort entries by factor
    factorwords.sort(key=lambda factor_and_word: factor_and_word[0])
    lines = []
    for num in numbers:
        words = ''.join(word for factor, word in factorwords if (num % factor) == 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)))
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

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)

Generator using counters instead of modulo

Works with: Python version 3.x
from collections import defaultdict

N = 100
FACTOR_TO_WORD = {
    3: "Fizz",
    5: "Buzz",
}

def fizzbuzz(n=N, factor_to_word=FACTOR_TO_WORD):

    factors = defaultdict(list)

    for factor in factor_to_word:
        factors[factor].append(factor)

    for i in range(1, n+1):
        res = ''
        for factor in sorted(factors.pop(i, ())):
            factors[i+factor].append(factor)
            res += factor_to_word[factor]
        yield res or i

if __name__ == '__main__':

    n = int(input('Enter number: '))

    mods = {
      int(k): v
      for k, v in (
        input('Enter "<factor> <word>" (without quotes): ').split(maxsplit=1)
        for _ in range(3)
      )
    }

    for line in fizzbuzz(n, mods):
        print(line)

Sieve of Eratosthenes

This variant uses ranges with step 3, 5, etc. Preserves order and duplicate moduli.

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))
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.

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"))

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.

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)

Racket

Translation of: Python
#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")))
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
(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"))
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
# General case implementation of a "FizzBuzz" class.
# 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;
    }
}


# 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;
}

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

say '';

# 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>);
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:

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>);

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
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

/*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. */
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

/*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. */
output   is identical to the 1st REXX version.


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

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)
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

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);
        }
    }
}

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

use std::collections::BTreeMap;
use std::fmt::{self, Write};
use std::io::{self, Stdin};

#[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(())
}

#[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);
    }
}

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

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)
  }
}

LazyList (f/k/a Stream)

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)
}

Scala 3 (Dotty)

Translation of: LazyList (f/k/a Stream)
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)

Sidef

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 }
Output:
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

SQL

Works with: ORACLE 19c

This is not a particularly efficient solution, but it gets the job done.

/*
This code is an implementation of "General FizzBuzz" in SQL ORACLE 19c 
*/
select lpad( nvl(   case when mod(level, 3) = 0 then 'Fizz' end 
                 || case when mod(level, 5) = 0 then 'Buzz' end 
                 || case when mod(level, 7) = 0 then 'Baxx' end
                , level)
            ,12) as output
  from dual
connect by level <= 107
;
/
Output:
           1
           2
        Fizz
           4
        Buzz
        Fizz
        Baxx
           8
        Fizz
        Buzz
          11
        Fizz
          13
        Baxx
    FizzBuzz
          16
          17
        Fizz
          19
        Buzz
    FizzBaxx
         ...
         101
        Fizz
         103
         104
FizzBuzzBaxx
         106
         107

Swift

import Foundation

print("Input max number: ", terminator: "")

guard let maxN = Int(readLine() ?? "0"), maxN > 0 else {
  fatalError("Please input a number greater than 0")
}

func getFactor() -> (Int, String) {
  print("Enter a factor and phrase: ", terminator: "")

  guard let factor1Input = readLine() else {
    fatalError("Please enter a factor")
  }

  let sep1 = factor1Input.components(separatedBy: " ")
  let phrase = sep1.dropFirst().joined(separator: " ")

  guard let factor = Int(sep1[0]), factor != 0, !phrase.isEmpty else {
    fatalError("Please enter a factor and phrase")
  }

  return (factor, phrase)
}

let (factor1, phrase1) = getFactor()
let (factor2, phrase2) = getFactor()
let (factor3, phrase3) = getFactor()

for i in 1...maxN {
  let factors = [
    (i.isMultiple(of: factor1), phrase1),
    (i.isMultiple(of: factor2), phrase2),
    (i.isMultiple(of: factor3), phrase3)
  ].filter({ $0.0 }).map({ $0.1 }).joined()

  print("\(factors.isEmpty ? String(i) : factors)")
}
Output:
Input max number: 20
Enter a factor and phrase: 3 fizz
Enter a factor and phrase: 5 buzz
Enter a factor and phrase: 7 baxx
1
2
fizz
4
buzz
fizz
baxx
8
fizz
buzz
11
fizz
13
baxx
fizzbuzz
16
17
fizz
19
buzz

Tailspin

def input: {N: 110"1", words: [ { mod: 3"1", word: 'Fizz' }, { mod: 5"1", word: 'Buzz'}, {mod:7"1", word: 'Baxx'}]};

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

[ 1"1"..$input.N -> '$->sayWords;' ] -> \[i](<=''> $i ! <> $ !\) -> '$;
' -> !OUT::write
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:

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}

Ursa

This program reads a max number, then reads factors until the user enters a blank line.

#
# general fizzbuzz
#
decl int<> factors
decl string<> words
decl int max

# get the max number
out ">" console
set max (in int console)

# 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

# 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

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

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
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

'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
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

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
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

Vlang

import os
 
fn main() {
    max := os.input('Max: ').int()
    f1 := os.input('Starting factor (#) and word: ').fields()
    f2 := os.input('Next factor (#) and word: ').fields()
    f3 := os.input('Next factor (#) and word: ').fields()
 
    //using the provided data
    words := {
        f1[0].int(): f1[1],
        f2[0].int(): f2[1],
        f3[0].int(): f3[1],
    }
    keys := words.keys()
    mut divisible := false
    for i := 1; i <= max; i++ {
        for n in keys {
            if i % n == 0 {
                print(words[n])
                divisible = true
            }
        }
        if !divisible {
            print(i)
        }
        println('')
        divisible = false
    }
}
Output:
Max: 20
Starting factor: 3 Fizz
Next factor: 5 Buzz
Next factor: 7 Baxx
1
2
Fizz
4
Buzz
Fizz
Baxx
8
Fizz
Buzz
11
Fizz
13
Baxx
FizzBuzz
16
17
Fizz
19
Buzz

Wren

Library: Wren-sort
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)
}
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

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);
}
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
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