37.50.48

%20 の ブログ

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以外 にできれば分岐ができる。

01 をスタックに積むのは短く書けるので書けばよい。

最初に入力を1回読んで無条件で 1 を出力するようにして、そこにラベルを設置した。

num_in だとEOFを読むだけでは終わってくれないが、今度はゼロ除算で終わってくれるようになった。めでたしめでたし。