LoginSignup
4
1

More than 3 years have passed since last update.

【TypeScript】仕様変更に強いFizzBuzz

Last updated at Posted at 2020-07-09

ネタ元:「fizzbuzzについて思うこと」
Kotlin版:【Kotlin】仕様変更に強い FizzBuzz

FizzBuzz の、割る数、出力する文字列、変換規則の数や順番が変わっても
最小限のコード変更で済むようにする。

/**
 * FizzBuzz の変換規則を表す型。
 * 入力された数値を割る数と、
 * 割り切れたときに出力に追加する文字列との組の列。
 */
type FizzBuzzMap = Iterable<
    Readonly<[number, string]>
>;

/**
 * FizzBuzz で入力された1つの数値を
 * 変換規則に従って文字列に変換する
 * 関数を返す。
 * 
 * @param map 変換規則。
 * @returns 数値を文字列に変換する関数。
 */
function fizzBuzzFunctionCreator(
    map: FizzBuzzMap
): (num: number) => string {
    return (num: number) => {
        const strs: string[] = [];
        for (const entry of map) {
            if (num % entry[0] == 0) {
                strs.push(entry[1]);
            }
        }
        return strs.length > 0 ? strs.join("") : `${num}`;
    };
}

使用例

普通の FizzBuzz

/** 変換規則の定義。 */
const FIZZ_BUZZ_MAP: FizzBuzzMap = [
    [3, "Fizz"],
    [5, "Buzz"],
];

/** 数値を変換規則に従って変換する関数。 */
const fizzBuzzFunction: (num: number) => string
    = fizzBuzzFunctionCreator(FIZZ_BUZZ_MAP);

for (let i = 1; i <= 15; ++i) {
    console.log(
        fizzBuzzFunction(i)
    );
}

出力

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

Fizz と Buzz の優先順を入れ替える

const FIZZ_BUZZ_MAP: FizzBuzzMap = [
    [5, "Buzz"],
    [3, "Fizz"],
];

// 他は同じなので省略

出力

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
BuzzFizz

こんなことも

const FIZZ_BUZZ_MAP: FizzBuzzMap = [
    [1, "<"],
    [3, "Fizz"],
    [5, "Buzz"],
    [1, ">"],
];

// 他は同じなので省略

出力

<>
<Fizz>
<>
<Buzz>
<Fizz>
<>
<Fizz>
<Buzz>
<>
<Fizz>
<>
<FizzBuzz>

/以上

4
1
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1