読者です 読者をやめる 読者になる 読者になる

チューリング不完全

What are you afraid of? All you have to do is try.

Wolfram AlphaでFizzBuzz

数ヶ月前にこんなツイートをしました。


今更ながら、ちょっと解説記事を書こうと思い立ったので書きます。
ブログ開設による推進力というやつです。

Map[ReplaceAll[GCD[#,15], {15 -> "FizzBuzz", 3 -> "Fizz", 5 -> "Buzz", _ -> #}]&, Range[100]]

上記のコードを実行すると以下のようになります。
f:id:aomori-ringo2:20120626191256p:plain


解説(なげやり編)

Range
Map
ReplaceAll
GCD

リファレンス貼っときました。以上。







嘘ですごめんなさい。わかんねぇよ、という方は丁寧編にお進みください。

解説(丁寧編)

では少しずつ分解していきましょう。
まずはMap, Rangeから。



Map: 第2引数に与えるリストの要素を1つずつ取り出して、第1引数の式を適用させる
Range: 1からnまでの整数のリストを返す

Map[#^2&, Range[10]]


Result: {1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

このとき、#は取り出した要素を表します。
&は、#がある式の最後に付ける必要のある記号で、演算子とかではないです。


続いてGCDです。
GCD: 最大公約数を返す
これをMap, Rangeと組み合わせるとこうなります。

Map[ GCD[#, 15]&, Range[30] ]


Result: {1, 1, 3, 1, 5, 3, 1, 1, 3, 5, 1, 3, 1, 1, 15, 1, 1, 3, 1, 5, 3, 1, 1, 3, 5, 1, 3, 1, 1, 15}


これに対してあとはReplaceAllを適用して完成です。
ReplaceAll: リストに対して変換の規則を適用する

ReplaceAll[ {x, y, z, a}, {x -> m, y -> n} ]


Result: {m, n, z, a}

パターンマッチですね。


このReplaceAllを使って、先ほどのGCDの式に
・15だったら"FizzBuzz"に変換
・3だったら"Fizz"に変換
・5だったら"Buzz"に変換
・それ以外だったらそのままの数字
というのを書きます。

Map[ReplaceAll[GCD[#,15], {15 -> "FizzBuzz", 3 -> "Fizz", 5 -> "Buzz", _ -> #}]&, Range[100]]

できあがり。

駄文

ReplaceAllには「/.」、Mapには「/@」というシンタックスシュガーが用意されています。
(Wolfram Alphaに今回のFizzBuzzの式を入力すると、Inputとして「/.」「/@」という記号に変換されているのが確認できます。)
Mathematicaではもちろん常に使用できますが、Wolfram Alphaでは入力の複雑さによって読み取ってくれたりくれなかったりします。


Mathematica勉強会でも以前この話を出してみたら、

  • 式が読み取れる場合と読み取れない場合の違いがよくわからない
  • シンタックスシュガーを使っても使わなくても本質的には違いがないのに使えなくなる意味がわからない

などの話が現れ、最終的に
「Wolfram Alphaのパーサはクソ」
という結論になっていました。