37.50.48

%20 の ブログ

五月祭2020 Live CodeGolf Contest Day2 参加記

TSG LIVE! 5(2日目)のライブコードゴルフ大会に、こたつがめさんとともに外部ゲストプレイヤーとして参加させてもらいました。

TSG LIVE! でコードゴルフ大会が行われていることは以前から知っていて、参加したいと思っていたので、参加できる機会を与えてくださったことに感謝しています。

リンク

競技規則

  • 競技時間は75分
  • 出力の空白・改行は余計にあってもよい
  • 出力が正しければエラー終了でもよい
  • 出力が正しく言語内最短を更新したときのみマスをとれる
  • 自分チームがとったマスと隣接するマスにのみ提出できる
  • 自分チームの提出コードは見ることができる
  • 相手チームの提出コードは見ることができない
  • 相手チームの提出言語、ジャッジ結果、コード長、提出時刻、提出者名は見ることができる
  • チームメイトとテキストでコミュニケーションをとってもよい

参加記

C

こたつがめさんが開始から3分で提出(55B)

main(a,p){for(;~scanf("%d",&a);)puts(p>a?p=a,"1":"0");}

ぱっと見で縮みそうなところがなかったので放置していた。結局これが最後まで最短として残った。

Ruby

とりあえずできたので提出した(38B)

x=100;p *$<.map{x>(a=_1.to_i)?a/x=a:0}

入力はランダムに1ケース作られるだけなので初期値を 99 にしてもバレなさそう(37B)

x=99;p *$<.map{x>(a=_1.to_i)?a/x=a:0}

p を内側に入れて * を消した(36B)

x=99;$<.map{p x>(a=_1.to_i)?a/x=a:0}

文字列として扱ったほうが短いよね(32B)

x=?:;$<.map{p x>_1 ? (x=_1;1):0}

まだ縮むような気もするが競技時間は75分しかないので別の言語へ。

後に相手チームのうらさんが提出したコード(31B)

s=?@
$<.map{p _1<s ?(s=_1;1):0}

それはそう。Rubyでは ? がいろいろな意味を持つので、条件演算子? の前後にスペースが必要になる場合があるが、この条件がややこしいので、分からなければ全部試すというのが有効で、きちんと試し切っていれば31Bにできていた。

Go

こたつがめさんがやっていた。Goに詳しくないので見ても分からないだろうと思い、ほとんど見ていない。

序盤にとりあえず提出し、終盤に縮めたようだ(87B)

package main
import."fmt"
func main(){p:=100;for{a:=0;Scan(&a);if p>a{p=a};Print(p/a)}}

Python3

Pythonは相手チームにも提出権があり、しかもRubyと似ているのでとりあえず提出した(54B)

x=':'
while 1:
 t=input()
 u=x>t
 if u:x=t
 print(u+0)

バージョンを確認していなかったので := をcheckerで試した結果、使えないらしいという結論を得ていた。

が、これは勘違いで、すぐにこたつがめさんが := を使って縮めていた(52B)

x=':'
while t:=input():
 u=x>t
 if u:x=t
 print(u+0)

:= を使って縮むところがもう1か所(50B)

x=':'
while t:=input():
 if u:=x>t:x=t
 print(u+0)

単項の + でも整数に変換できるらしい(49B)

x=':'
while t:=input():
 if u:=x>t:x=t
 print(+u)

後に相手チームのhakatashiさんが提出したコード(48B)

j="Z"
for n in open(0):j=min(j,n);print(1-(j<n))

Python3ゴルフで入力を読み込む常套手段である open(0) を利用しているが、実は while t:=input():for n in open(0): の字数は同じ。

今までに見た中での最小値を更新してしまってから更新があったかどうかを判定しているのが短縮ポイントらしい。

Perl

相手チームはPerlの提出権がないのでGolfScriptをやろうとしていたが、できなかったのでPerlをやった。

とりあえず提出したコード(29B)

print$~gt$_?$_/($~=$_):0for<>

$~ は初期値が "STDOUT" なので、"99\n" よりも辞書順で大きい。結局これが最後まで最短として残った。

終了後の今見ると、ジャッジ環境の $$(PID)の値次第だが縮む可能性がある(28B)

print$$>$_?$_/($$=$_):0for<>

GolfScript

こたつがめさんがやっていた(27B)

今までにGolfScriptを触った経験から、もっと縮むはずと思っているので詳細は省略。

相手チームが提出してこなかったので一応勝ちは勝ち。

Crystal

こちらのチームがGolfScriptに提出したのを見て相手チームが防衛のために縮めていたらしい。

元々のコード(60B)

j=99
while l=read_line.to_i
p(if j > l
j=l;1
else
0
end)
end

縮めた後のコード(42B)

j="Z"
STDIN.each_line{|n|p j>n&&(j=n)?1:0}

見るからに入力を読み込む部分が長いなぁという印象。

Crystalは一応書いたことはあるものの、入力の読み込み方を忘れたので調べてみると、gets でできるらしい。

後置 while$_gets で読み込んだ文字列が自動的に代入される変数)がないことに対して不便だなぁと思いながら適当に書いたら相手チームより短かった(39B)

x=":"
while s=gets
p x>s ?(x=s;1):0
end

直後にこたつがめさんが1B縮めた(38B)

x=":"
while a=gets
p x>a ?(x=a;1):0end

Whitespace

相手チームの提出権がないので急ぐ必要はないものの、残り時間も減ってきたのでやった(79B)

スペースを S、タブを T、改行を N に変換したコードで解説する。

コード 意味 備考
SS(S)[TTSSTSS]N push 100 (S)=+,[TTSSTSS]=100
NSS[]N label "" ラベル名は空にできる
SNS dup  
SNS dup  
SNS dup  
TNTT readnum 整数の入力を1行読み込み、配列の(top of stack)番目に代入する
TTT retrieve 配列の(top of stack)番目の値をスタックに載せる
STS(S)[T]N copy 1 (S)=+,[T]=1
TSST - (読み込んだ値)-(現在の最小値)
NTT[S]N jump(<0) "S"  
SS(S)[]N push 0 0の場合は符号だけで可
TNST writenum  
NSN[]N jump ""  
NSS[S]N label "S"  
TTT retrieve もとの最小値が今スタックトップにあることを利用
SS(S)[T]N push 1  
TNST writenum  
NSN[]N jump ""  

以前は古いPCでWhitespace用のエディタを自作して使っていた(バックアップはとっていなかった)のだが、そのPCが割と最近壊れたので、メモを紙に書いた後、普通のエディタで書いた。その結果、少し間違えた(ちょうどその部分が放送で映されている)。

終了後に見返すと、自明な無駄と容易な改善方法があって、計6B縮む。

3連続dupは1回余計で、全く使われることなく残ってしまう要素があるので2連続dupでよい(76B)

分岐の仕方を、a-b<0?c:d から b-a<0?d:c に変えることで、copy 1 の代わりに dup が使えるようになる(73B)

コード 意味 備考
SS(S)[TTSSSTT]N push 99  
NSS[]N label ""  
SNS dup  
SNS dup  
SNS dup  
TNTT readnum  
TTT retrieve  
TSST - (現在の最小値)-(読み込んだ値)
NTT[S]N jump(<0) "S"  
TTT retrieve  
SS(S)[T]N push 1  
TNST writenum  
NSN[]N jump ""  
NSS[S]N label "S"  
SS(S)[]N push 0  
TNST writenum  
NSN[]N jump ""  

><>

Whitespaceの前に書こうか迷っていた。こたつがめさんが46B、45B。たぶんまだ縮むので詳細は省略。

相手チームの提出権がないので縮める必要もなかった。

この言語の厄介なところは、入力を1Bずつしか読み込めないことと、エラーメッセージが全て同じことで、命令が豊富な割に、書いてみると結構つらい。

Node.js

よく知らない。相手チームがやっていた。提出権はあったのでやろうとしても良かったかもしれない。

Starry

終盤でCrystalをとったことで提出権を得たが、時間が足りないのでやろうとしなかった。

分岐命令が !=0 しかないので書きづらいが、方針は立っているのでそのうちやりたい(やるとは言ってない)