TSG LIVE! 5 2日目のコードゴルフの問題をStarryで解いた
うらさんの記事 を参考にしました。
Starryの標準入力の仕様について詳しくなかったので調べた。
この言語のインタプリタはRubyで実装されていて、入力に関する部分は次のようになっている。
when :char_in
push($stdin.getc.ord)
when :num_in
push($stdin.gets.to_i)
EOFを読み込むと、char_in
では undefined method `ord' for nil:NilClass (NoMethodError)
となってエラー終了するのに対し、
num_in
では nil
が整数に変換され、スタックに 0
が積まれる(終了しない)。
EOFで自動的に終了してくれたほうが楽なので char_in
を使って書いた(83B)
+ + + * + **` + , , + , ** + + * +. + + * + + * * * +'
今回の問題では大小比較をして 0
または 1
を作りたいので、大きめの整数 x
を使って (a+x)/(b+x)
のような切り捨て除算をするという方法が考えられる。
, , + , **
の部分が入力を読む部分で、改行の文字コードが 10
なのを利用して、十の位を表す数字の文字コードを10倍するのに使っている。
(例:"39\n"
は文字コード列では 51,57,10
なので、57+51*10=567)
これにより、10~99は538~627に変換される。
最初に仮の最小値としてよい値は627~1075ということになる。上のコードでは5+(5^2)^2=630にした。
入力の最初の要素が98か99のとき以外なら625でも通るという嘘解法をすると3B縮む。
Pythonでいうとこんな感じ(意訳)
a=630
while True:
b=int(input())+528
c=a//b
print(c,end='')
a=b*c-a*(c-1)
num_in
を使ってみたが、長かった(92B)
+ +* + * +* +,` + +* + ** + + * +. + + * + + * * * +, +'
意訳
a=200
b=int(input())
while b!=0:
b+=100
c=a//b
print(c,end='')
a=b*c-a*(c-1)
b=int(input())
200を作るために100を経由するので、スタックに常に100を残しておけば縮むかも?という気はするが、dupしかないのでつらい。
追記
なんかめっちゃ縮んだ(37B)
,` + `. +, + + *' + + '
割り算した結果を 0
または 1
にする必要はなくて、0
または 0以外
にできれば分岐ができる。
0
や 1
をスタックに積むのは短く書けるので書けばよい。
最初に入力を1回読んで無条件で 1
を出力するようにして、そこにラベルを設置した。
num_in
だとEOFを読むだけでは終わってくれないが、今度はゼロ除算で終わってくれるようになった。めでたしめでたし。