Most tweetable 1-liner

もっともツイート可能なワンライナー

受賞者:Yusuke Endoh

引用元:https://www.ioccc.org/2013/endoh3/endoh3.c

審査員・作者による説明:https://www.ioccc.org/2013/endoh3/hint.html

動作

次のように実行する。

$ gcc -o endoh3 endoh3.c

$ echo 'CDEFGABc' | ./endoh3 | ruby wavify.rb > cde.wav

cde.wavを再生すると、ドレミファソラシドが流れる。 音量に注意。

音:cde.wav

きらきら星。

$ cat twinkle.abc | ./endoh3 | ruby wavify.rb > twinkle.wav
音:twinkle.wav

メヌエット

$ cat menuet.abc | ./endoh3 | ruby wavify.rb > menuet.wav
音:menuet.wav

解説

ABC記譜法のサブセットから音楽データを合成する。

対応している機能は次の通り。

楽譜データのパースはscanf(" %c%f")で行う。 音符を音程に変えるのは、ブルートフォースで見つけた次の式。

(a % 32 + 5) * 9 / 5 % 13 + a / 32 * 12 - 22

音符のASCIIコードをaに入れてこの式を計算すると、次のように音程の数字が得られる。

シャープやフラットの記法(^C_C)には対応していないが、次の文字で音を出すことは可能。

この音程の数字に対してpow(2, n / 12.0)を計算すれば周波数が得られる。 しかしpowは使えないので、pow(2, 1 / 12.0)89/84.0n回掛けることで算出する。

そして、次の計算で出力を行う。

for(c = 0; c < 音符の長さに相当する回数; c++) putchar(a = c * D);

achar型の変数、Dが周波数、cはカウンタ。 aに代入することで、D * cを256で割った余りになるので、のこぎり波が出力されることになる。

以上の処理を1つのfor文で行うことで実現されている。

細かいことだが、scanf(" %c%f")でパースする都合上、C2E2とは書けない。 2e2が浮動小数点数リテラルとみなされるため。 C2 E2のようにスペースをあけば回避できる。

賞名の”tweetable”は、「さえずる」という意味と、Twitterにツイート可能という意味を重ねている。 当時のTwitterの文字数制限(140文字)に収まるコードなので。