全国統一プログラミング王決定戦決勝 参加記

2019/02/17に行われた全国統一プログラミング王決定戦決勝に参加してきました。日帰りです。

・決勝前

朝は目覚ましが鳴る前に起きました。 東京駅に着いたのは10時半あたりで、一瞬だけゲームセンターに行きました。

・決勝

意識がない

・決勝後

エキシビションマッチでは速解きコンテストが行われました。 速解きコンテストではコードゴルフをしろと蟻本にも書いてあります。 幸いエキシビションマッチ終了直後からコンテストページがオープンになったので、懇親会の最中に縮めてしまうことにします。

コードゴルフをしていたと思ったらいつのまにか懇親会が終わっていた

新幹線の終電に乗ることにして、%20さんとうらさんと店に入ってコードゴルフの続きをしたりしました。

エキシビションマッチのA-F問題で僕が提出したコードを載せます。(家に帰ってから提出したものも含む)

A問題

1..length(S)を出力します。

Perl6 16B

put 1..get.chars

length(S)=get.charsです。これは改行区切りではなく空白区切りになりますが通ります。

Bash 16B

read s;seq ${#s}

length(S)=${#s}です。

最短はRuby 15Bでした。負け

B問題

floor(sqrt(N))を出力します。

Awk 13B

$0=int($0^.5)

まあ……

Perl 13B

print<>**.5|0

bit演算をすると非負整数型にキャストされます。

C問題

N mod 11を出力します。

Awk 6B

$0%=11

N mod 11=0のときこのコードは出力を行わずWAになりますが、そのようなケースは存在しないので通ります。

D問題

10^(N-1)を出力します。

Perl 15B

print+1,0 x~-<>

1の後に続けて0N-1回繰り返した文字列を出力します。

Perl6で10^(N-1)をするとTLEしました。

E問題

FizzBuzzっぽいことをします。詳しくは問題文を見てください。

Perl6 46B

(.++;say chrs(95 X+grep $_%%*,2..6)||$_)xx get

.++;say chrs(95 X+grep $_%%*,2..6)||$_get回繰り返します。ループです。

まず.++$_をインクリメントします。ループ変数です。

grep $_%%*,2..62..6のうち$_を割り切る数だけを抜き出し、95 X+でそれぞれに95を加えます。出力すべき文字コードのリストになります。 chrsに適用して文字コードに対応した文字列を得ます。空文字列だった場合はchrs()||$_の右辺が評価され、$_になります。 それを出力すればよいです。

Perl 53B

$i=//,print+(@a=grep$'%++$i<1,a..e)?@a:$',$/for 1..<>

後置forでループします。

//$_とマッチングを試します。空文字列はいかなる文字列にもマッチするので、1が返り、$iに代入されます。 副作用として、$'にマッチングした位置より後ろの文字列が代入されます。//は文字列の先頭にマッチするはずなので、$' eq $_が成り立ちます。

grep$'%++$i<1,a..eで、a..eのうち出力するべき文字を抜き出しています。 各ループで$iはインクリメントされ、$iは事前に1に初期化されているので、aには2bには3……とうまく対応できています。 こうして得られたリストを@aに代入します。

三項演算子によって、@aが空でなかった場合@aが、空であれば$'print関数に渡され、$/とともに出力されます。

このコードは%20さんによって52Bに縮められました。

F問題

N+1項のコラッツ数列を作り出す10^16未満の初期値を出力します。

Perl6 53B

(1789997546303,{$_%2??$_*3+1!!$_/2}...1)[1e3-get].say

N=1000のときの答えを初期値にしてコラッツ数列を作り、第1001-N項を出力します。

{$_%2??$_*3+1!!$_/2}は数列を作る漸化式で、これと初項をもとに数列を作成できます。

1789997546303を初期値にすると、最大値が10^16未満であるコラッツ数列が得られるので、これを初項にすればよいです。

実は初期値は1412987847でもよく、これを利用したriantkbさんによって50Bに縮められました。