naiの日記

ソフトウェアエンジニアから放射線科診断医にジョブチェンジしました。趣味のことを書きます。

334. Sokoban

Sorobanの直後に投稿された問題で、問題名と内容を見てちょっと笑ってしまいました。
下から3ビット目をへし折るだけの簡単な問題ですが、42Bの投稿者で-5との論理積を取っているのは自分だけで、他の方はみな~4との論理積を取っていました。
この辺の書き方の違いは面白いですね。自分は~4を瞬時に-5と解釈してしまったのでこうなったようです。

336. C style constants

チートくさいのでもう書いてしまいますが、38Bはsystem("perl")です。というか、perlの最短コードをそのままsystemの中に書いただけです。
これだけ単純な問題なので、execを許すならもっと縮むのではないかと思いましたが、自分はCとPerl以外は門外漢なので……

332. Soroban Fixed

終了しました。


ループカウンタをどのように設定するかが一番のポイントだったようです。
1・4・10回目のループは珠でなくそろばんの枠を出力しなければならないので、1・4・10回目が簡単な条件式で判定できなければなりません。
自分は1から2ずつ増やしてi=1,7,19のときに枠を出力するようにしました。7と19が素数のため133%iで判定できます。
ところがnnさんのコードはi=9からのカウントダウン方式。判定はi%9%6で私のコードと同じく5Bとできるし、iの値がそのままforの条件式に使えるなど、さまざまな利点があります。言われてみれば納得ですが、こういうのを思いつけるのはすごいです。
その他、珠を出力するところでも自分のコードはやや冗長だったようです。うーん、やっぱりもっと考えないとな。

唯一自分が勝っていたのは"=*="を出力するところでstrlenを使っていないところだけでした。
実はかなり後半までstrlenを使っていたのですが、ある程度縮んだにも関わらずalnumがダントツのトップだったので、これは皆さんstrlenは使っていないに違いないと考え最終コードに到達しました。
なので半分カンニングのようなものです……


さて、post mortemで自分が130BをSubmitしたわけですが、コードをご覧になれば分かる通り私はほとんど何もしていません。
なのでこのまま終わるのもアレかと思いどうにか縮まないかいろいろ試してみたのですが、やはり難しいですね……。
実は改行にputsを用いたコードが思いの外縮んだのですが、惜しくも130B止まりでした。悔しいので後でまた挑戦します。

328. base convert

サークルの合宿やら試験やらでずっと更新できない状態が続いていましたが、漸く暇が出来ました。

328. base convert

一位のnnさんの解は凄いですね。無駄がありません。
再帰関数を作り逆順で出力する方法しか考えていなかったので、これには参りました。
自分はどうにかscanfの引数を削り81Bまで縮めましたが、それまででした。

330. Sort by Length for OCaml Golf Competition

かるたの合宿等と被ってまったく参加できず。
とりあえず問題文を読んで方法を考えていましたが、コンパレータを定義してqsortに突っ込む方法しか考えていなかったので、inaniwaさんの解のようにstrcmpでソートしてから全部なめて短い順に出力するのはまったく想定外でした。これも凄いですね。



その他の問題はまだ思考がまとまっていません。
タイミング良くActive Problemsがたくさんあるので、一つずつ考えていこうと思います。


ちなみに、かるたの職域で大学OBの凄腕Golferの方とお会いしました(あなごるで非常に高い成績を出している方です)。
大学の先輩に何人か素晴らしいGolferの方々がいらっしゃるのは知っていましたが、かるたの先輩にいらっしゃるとは。世界は意外と狭いものですね。

322. Substract from a Googol

私生活でいろいろあってしばらくゴルフから離れていましたが、とりあえず再開です。

322. Substract from a Googol

締め切り直前のSubmitすみません。なぜかいつも締め切りギリギリでのSubmitになってしまう……
今回は途中寝落ちしてしまったこともあり、縮めている間に終了という初めての事態に。

sprintfの書式指定によりスペース(32)が左に入るので、15との論理積を取ると0になり、leading zeroと同じ効果が得られるというわけです。

324. Googol division

こちらも終了しました。
最初は左端に0を出力してしまうのをどうにかしなければと悩んでいましたが、単純にr=10000から始めて解決。ついでにforの条件式も1バイト減りますね。

321. add_sub_brainfuck_code

ちょっと遅くなってしまいましたが。
nuさんmskさんの解のように、readの第一引数に変数を入れることで条件分岐するというのは全く思いつきませんでした。凄いですね。

314. Roman numeral

終了しました。


トップのinaniwaさんの解はなんと93B。
減算則のチェックに、直前の値を保存せず、合計値を表す変数sが現在の値aで割り切れるかどうかで判定しています。
なるほど、確かにaの値は通常は広義単調減少で、しかも過去の値はすべて現在の値の倍数なので、これでチェックできますね。まったく思いつきませんでした。


他の人のコードも見ていて面白いです。
nnさんは、「500と1000が一発で表せない」という一番の問題をワイド文字で解決していて衝撃的でした。
nuさんは、-10と負数の論理和を取ることで-1と-10を作れているうえに、一つ答えを表示したときにprintfの返り値をs,p両方に代入することでs=0にする手間を省いています。
与えられた入力は、2行目以降で1バイト目に"I"が出てくるデータがないため次のループでs-=pされて消えるのですが、これは思いつかなかったです。
ちなみに私は、printfの書式"%d\n"の2,3,4バイト目の文字コードがそれぞれ100,10,0であることを利用しているのですが、3桁バイトの壁を越えることは出来ませんでした。


みなさん、お疲れ様でした。

317. Multiplication Table

終了しました。
deadlineギリギリでの投稿、失礼しました。
(一応言っておきますと、隠し玉として温存していたわけでは決してありません)

終了直前までは

i;main(){for(;i-144;)printf("%3d%c",~(i++/12)*~(i%12),~i%12?32:10);}

この68Bだったのですが、printf第三引数で行っていた改行判定を第一引数にも持ってくることが出来ることに気づき、そこから変数を1つ増やして63Bを通すことが出来ました。

ちなみに、終了後の62Bはinaniwaさんのコードを見て思いつきました。


この問題も、単純な割に幾通りものアプローチがあって面白い問題だと思うのですが、惜しむらくは、(Another Tableの出汁にされたためか)deadlineが非常に早かった点です。
もう少しゆっくり解きたい問題でした。