Help us understand the problem. What is going on with this article?

最短であってほしい Julia の FizzBuzz

More than 1 year has passed since last update.

科学技術計算で最近流行りの Julia。FizzBuzz で練習しました。使用バージョンは 1.1.0。

普通のやつ (131 byte)

for i in 1:100
    if i % 3 == 0 && i % 5 == 0
        println("FizzBuzz")
    elseif i % 3 == 0
        println("Fizz")
    elseif i % 5 == 0
        println("Buzz")
    else
        println(i)
    end
end

余計な空白をなくして長さを計算すると137 byte

文字列結合パターン(92 byte)

 Fizz も Buzz も2回ずつ登場しているのが8byteの無駄です。println文も一度で良いでしょう。そこで,最終的に出力する文字列のために変数を1つ用意することにした黄金パターン。この方針で短くしていきます。

for i in 1:100
    s = ""
    if i % 3 == 0
        s = "Fizz"
    end
    if i % 5 == 0
        s *= "Buzz"
    end
        println(s == "" ? i : s)
end

if 文なし (87 byte)

 if 文は end で結ぶ必要があるので無駄です。Julia には三項演算子があるのでそちらを用います。しかし,実は三項演算子のスペースが削れない関係で,そこまで短くできない……

for i in 1:100
    s  = i % 3 == 0 ? "Fizz" : ""
    s *= i % 5 == 0 ? "Buzz" : ""
    println(s == "" ? i : s)
end

代入は一回で(82 byte)

 三項演算子を用いた代入が2回あるのが無駄に見えます。要は,Fizz・Buzz のあるなしを区別できれば良いので,文字列の繰り返しや結合を駆使します。
 Julia では,多くの言語と少し変わって,文字列の結合は*1,繰り返しは^を使います。

for i in 1:100
    println((s = "Fizz"^((2 - i % 3) ÷ 2) * "Buzz"^((4 - i % 5) ÷ 4))=="" ? i : s)
end

 文字列の繰り返しを1回にしたり0回にしたりすることで Fizz, Buzz の出力をコントロールしている感じです。Julia の ÷ は整数へと切り捨てる割り算になります(Python3 の //相当)。

最後の切り詰め(69 byte)

 Julia に詳しい人たちにアドバイスをもらい,

  • for の代わりに ブロードキャストを使った繰り返し(mapを使うよりも短い)。
  • x=...==""の部分をx=...>""とする
  • (2 - i % 3) ÷ 2の部分で,インデックスを1ずらすことによりi % 3 ÷ 2でできるように

という工夫の結果,69 byteまで短縮しました。

(i->println((x="Fizz"^(i%3÷2)*"Buzz"^(i%5÷4))>"" ? x : i+1)).(0:99)

最後に

ゴルフ向きの Perl には敵わないとしても,Python3 で 49 byte とか出ているみたいなので,せめて 60 台には載せたかったです。みなさまのご協力お待ちしております。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away