literate C.js

つい最近は、あなごるの literate C という問題が終了した。この問題は、以下のようなルールになっている。

hoge
fuga
>hoge
>fuga
piyo
>piyo

上記のようなテキストファイルがあったとする。

  • hoge のように、行の最初の文字が >ないならば、その行をコメントと呼ぶ
  • >hoge のように、行の最初の文字が >あるならば、その行をコードと呼ぶ

行がコメントなら、/* hoge */ と出力し、コードなら、hoge と出力する。ただし、2 行以上コメントが続く場合は、まとめて /**/ で括り、インデントを入れる必要がある。

すなわち、上記ファイルの正しい出力結果は以下となる。

/* hoge
   fuga */
hoge
fuga
/* piyo */
piyo

JavaScript で投稿したところ、単独トップを取ることができた。

for(d=0;;d=s&&">"!=s[0]?v=d?v+"\n   "+s:s:(d&&p("/*",v,"*/"),p(s.slice(1))))s=readline(p=print)

これが、そのコードだ。サイズは 95B.

基本的なロジックはそのままに、わかりやすさを重視して改変すると、概ね以下のようになる。

for (d = false;;) {
  s = readline();

  if (s && s[0] != ">") {
    if (d) v += "\n   " + s; else v = s;
    d = true;

  } else {
    if (d) print("/*", v, "*/");
    print(s.slice(1));
    d = false;
  }
}

一行だけ読み取り、それがコメントなら、v に追記していく。そうでなければ、v を出力し、かつ、現在行も出力する。

細かいところを省略すると、だいたい、そのような処理になっている。

変数 d には、直前の行がコメントであったかどうかの真偽値が入っている。それによって、コメントである現在行を v に追記するのか、それとも、v を現在行で上書きするのかという処理の分岐が行われる。加えて、現在行がコードであった場合、v を出力するかどうかの判定も行う。直前の行が、コメントなら、v を出力する必要があるが、コードなら、出力するわけにはいかないからだ。