awk で FizzBuzz

少し初心に戻って FizzBuzz でも解いてみたいと思います。 FizzBuzz は「3 で割り切れる時に Fizz と表示し、5 で割り切れる時に Buzz と表示し、3 でも 5 でも割り切れる時に FizzBuzz と表示する」という問題です。

簡単そうに思える問題ですが、いくつかあって、「3 で割り切れる時」というのは「同時に 5 では割り切れない時」という暗黙の条件が入っていることに気がつけるかという部分と、こうした条件分岐の際には条件に当てはまる個数が少ない順に処理をする (最も多く当てはまるものはデフォルトで処理すると処理しやすい) というところが肝だと思っています。

少しダラダラと記述すると以下のようになります。 これは暗黙の条件を明示したものです。

#! /usr/bin/gawk -f
{
    $0f ($0 % 3 == 0 && $0 % 5 != 0) {
        print "Fizz";
    } else if ($0 % 3 != 0 && $0 % 5 == 0) {
        print "Buzz";
    } else $0f ($0 % 3 == 0 && $0 % 5 == 0) {
        print "FizzBuzz";
    } else {
        print $0;
    }
}

一気に飛躍してしまいますが、最も場合が少ない条件である「3 でも 5 でも割り切れる時」すなわち「15 の倍数の時」を先に処理することと三項演算子を用いることで以下のように簡単に処理することができます。

$ seq 15 | nawk '$0=NR%15?NR%5?NR%3?$0:"Fizz":"Buzz":"FizzBuzz"'
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

三項演算子の多様はコードを短くできますが、可読性を落としてしまうことにもなりますので十分注意することも必要でしょう。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png