🍣

一日一処: ワンラインで判定するJavaScriptのFizzBuzz

2024/02/04に公開

FizzBuzz

FizzBuzzは、ピラミッド生成と同じくらい、基礎的な技能を測るプログラム課題として有名だと思う。特に、このような固有名詞で呼ばれるくらいであるため、これ自体のWikipediaのページが存在する。Wikipediaには、飲み会やドライブの雑談にも用いられるとあるが、遭遇したことがない。後述されているプログラムのほうが馴染みがある。今後機会があれば、飲み会やドライブ中にでも導入してみようと思う。

FizzBuzzのルール

至って簡単だ。どこかに、3に関連する数字を言うたびにおかしくなる人間がいたように、FizzBuzzでは、3の倍数にてFizz、5の倍数にてBuzz、両方と一致する15の倍数の際にはFizzBuzzと唱えるというルールだ。

1
2
Fizz
4
Buzz
Fizz

といった具合で、Wikipediaにもある通り、そこまで難しいプログラムにはならない。

まずは基本的な記述

最初にJavaScriptを用いて、基本的な記述でこれを実行してみる。1から始まり数値の最大は100とする。

for (let i = 1; i <= 100; i++) {
  let message = ''
  if (i % 3 === 0) {
    message = 'Fizz'
  }
  if (i % 5 === 0) {
    message += 'Buzz'
  }
  console.log(message === '' ? i : message)
}

先の例の通り100までFizzBuzzを交えながら出力してくれる。最後の出力部分も上と同じく条件分岐でも良かったが、三項演算子を用いてシンプルにした。

緩やかに短縮していく

せっかく三項演算子を用いたのだから、他の箇所でも用いなければ、もったいない。そのため次は、このように修正してみた。

for (let i = 1; i <= 100; i++) {
  let message = i % 3 === 0 ? 'Fizz' : ''
  message += i % 5 === 0 ? 'Buzz' : message
  console.log(message === '' ? i : message)
}

これでも十分短くなっただろう。
書き換わったプログラムを見ると、複数変数に代入しているのも整理できそうだ。

for (let i = 1; i <= 100; i++) {
  const message = (i % 3 === 0 ? 'Fizz' : '') + (i % 5 === 0 ? 'Buzz' : '')
  console.log(message === '' ? i : message)
}

短いコードに一歩近づいた。過去のピラミッド建造では、ここから、繰り返し構文の中に全部押し込めるという荒業を見せた。今回は、もう少し、モダンな書き方でワンラインを目指す。最後にこう書き換えれば、1行でシンプルなコードとなる。

console.log(Array(100).fill().map((_,i)=>((++i%3?'':'Fizz')+(i%5?'':'Buzz'))||i).join('\n'))

非常に短く、そして美しくなったのではないだろうか。特に三項演算子を条件を反転させたり、息数から得た配列番号を加算する点などは、芸術点が高いように思える。

Discussion