TSG LIVE! 5 ライブコードゴルフ大会 Day1 writeup

2020年五月祭で TSG が催したプログラミング生放送企画『TSG LIVE! 4』内のコーナー『ライブコードゴルフ大会』に参加した感想です。

新型コロナウイルスの影響により 9 月に延期(五月祭なのに)、さらにオンラインでの開催となりましたが、TSG LIVE! では今までと変わらないクオリティで企画を提供できたのではないかと思います。

今回自分は Day1 で作問および実況解説、Day2 でプレイヤーを担当したので、両方について触れていきます。

Day1

YouTube Live のアーカイブはこちらです。

youtu.be

スライドの作成者は自分なので、ここで出してしまいます。

問題概要

大文字か小文字かを判定せよ。

入力

  • ラテン文字 A から Z の 26 文字が順番に、一行で与えられる。
    • 各文字は大文字あるいは小文字である。
  • 入力の最後には改行が付与される。

出力

  • 与えられた文字それぞれについて、大文字であれば 1 を、小文字であれば 0 を出力せよ。
  • 出力された文字列に含まれる空白文字(改行含む)は無視される。

制約

  • 入力には必ず大文字がひとつ以上、小文字がひとつ以上含まれる。

入力例

ABCdefghiJKLmnopqRSTUvwxYz

出力例

11100000011100000111100010

コード

各言語の作問者解はスライドの方に載せました。補足したい部分について補足していきます。

C (44 bytes)

main(c){for(;c=getchar()>>5;)putchar(51-c);}

ナンさんの提出を見て思いましたが、最後が 51^c のほうが美しいですね。コードゴルフは芸術でもあるので美的感覚を養っていきたい所存です。

Python (33 bytes → 32 bytes)

for c in input():print(0+(c<"a"))

しーあるさんの Twitter の 2 日目に対する言及で気づきましたが、こちらも 0+(c<"a")+(c<"a") にできるので縮みますね。

Ruby (21 bytes → 20 bytes)

スライドでは

$<.bytes{p 80./_1-10}

と載せていますが、YouTube Live のコメントでこたつがめさんが

$<.bytes{p 2./_1>>5}

という解を載せてくれており、見事に取られてしまいました。ちなみにこたつがめさんは

頭がAtCoderだった

というコメントを残していますが、これは AtCoder と今回の esolang-battler のシステムの違いによるもので、AtCoder では正常終了しなければいけないのに対し esolang-battler では異常終了が許されています。というわけで過去の大会でもゼロ除算でループを抜けるなどの手法が典型になっているんですね~。

PPAP (131 bytes → 120 bytes)

I have 句を最初に書かなければいけないと思いこんでいたら、iLiss さんがライブ中に I have 句を途中に書いたコードを出していて、作問者解より短くなってしまいました。すごい。

これ以上のゴルフは面倒なのでやりません……。

FerNANDo (59 bytes → 45 bytes)

作問者解とプレイヤー解が一致し、もう縮まないだろうと思っていたのですが、YouTube Live で %20 さんが

最初に入力読まなくてもいいので縮むはず(改行を余計に出力すればいいので)

ferNANDo最初に空白を余計に出力すれば45B。7 7;7;0 0 7 9 0 0 0 6;9 8 7 6 5 4 3 2 1;6 6;7

といったコメントを残していました。実はライブ中に自力ではコメントを拾いきれておらず、口頭で伝えられてもどういう意味か瞬時に理解できなかったのが心残りですが、今考えるとたしかにそうでした。すごい。

Brainfuck (63 bytes)

,[+++++++++[[>]+<[-<]>]>>>>>>[->-<]+[+++++>+<]>---.,----------]

という解を載せており、ライブ中に説明するのは無理だと思ったのでここで解説します。

まず ,----------[++++++++++ ~ ,----------] は改行がくるまで読み込む典型的な方法です。

次の [[>]+<[-<]>] は 2 進数展開です。2 進数のインクリメントは末尾の 01...110...0 に置換することで再現できるということを考えると、そのセルの数分だけインクリメントを繰り返しているということがわかります。

+ が 1 つ足りませんがこれは A および a が 0b01?00001 で、1 足りなくてもビット判定に影響が無いからです。

次に 6 ビット目を見て、あったら 7 ビット目を消しています。7 ビット目は 1 が確定しているので反転に使えます。

+[+++++>+<] は wrap-around な処理系において 255 / 5 == 51 を用意するのに便利な典型的な方法です。

あとは、場所をもとに戻す必要がないので右に移動しながらループを繰り返すことになります。

Day2

n4o847.hatenablog.com