Rubyで競技プログラミングに挑む | Dev Driven 開発・デザインチーム Rubyで競技プログラミングに挑む | 働くひとと組織の健康を創る iCARE

BLOG

Rubyで競技プログラミングに挑む

iCAREのバックエンドエンジニアの師匠です。
もうすぐGWですね!

さて、自分は営業からエンジニアに転身したんですが、もうすぐエンジニアの実務歴が1年になります。

そして永遠とリモートワーク +出かけられない生活をしているわけで時間に余裕ができるわけです。

家を片付けたり開発環境を整えたんですが、それも一通りやるとある程度こんなもんかとなってきて暇なわけです。

ということでスキルアップも兼ねてatcoderさんで以前から興味があった競技プログラミングを始めて見ました。
しばらくは実務で使っているRubyで挑んでいきたいと思います。
(C++が競技プログラミングでは有利と言われていますが、限界がくるまでRubyでやりたいと思います)

ABCに参加してみよう


毎週AtCoder Beginner Contest(通称ABC)コンテストがあるんですが、そちらに参加しています。

問題はA-Fまであり、D以降がアルゴリズムや数学の知識が必要になります。正確さと速さでレーティングが上がっていきます。ゲームみたいですね。今はCまでをきちんと素早く解けるように練習しています。

今日はまだ始めたばかりということで、Rubyで競技プログラミングを解く際のお作法を記述していきたいと思います。

ABC163回 A問題

羊がS匹、狼がW匹います。
狼の数が羊の数以上のとき、羊は狼に襲われてしまいます。
羊が狼に襲われるなら unsafe、襲われないなら safe を出力してください。
入力はS Wの形式で与えられます。

答え

こちらが一番直近のコンテストの一番簡単な問題です。
問題は基本出力が与えられるんですが、Rubyではどのように処理したら良いでしょう?

このように短く書くことができます。
S, W = gets.split.map &:to_i

まず出力を取得するにはgetsを使ってあげれば良さそうです。

次に出力を分割したいですね。splitというメソッドを使ってあげれば良さそうです。

ちなみにこのメソッドは引数を指定し、それで分割するメソッドですが、nilの場合は先頭と末尾の空白を除いたうえで、空白文字列で分割することができるので出力の処理の上では引数の指定は必要ないですね。

文字列先頭と末尾の空白文字を全て取り除いた文字列を生成して返すstripというメソッドもありますが、splitで除去されているので必要ないですね。

最後にto_iを使ってinteger型に変換してあげます。
ここでmapを使っていますが、ここもコードを短くする工夫をしています。
mapはブロックを評価するのですが、to_iというメソッドが書かれていますね。ここは&が肝になり、 &は、blockをprocに、 procをblockに、そしてprocでないオブジェクトに対してto_procを呼んでからblockに変換することができます。
ちなみにここは弊社で毎週金曜日に行っている弊社技術顧問willnetさんが主宰するメタプログラミングRuby輪読会でも出てきたことでしたのでだいぶ理解できるようになりました。

最後にここまでできれば
puts S <= W ? 'unsafe' : 'safe'
と三項演算子を使って出力してあげれば完成です。

終わりに

いかがでしたでしょうか?
Rubyは短く記述することができるので、短いコードも意識してやっていきたいと思います。
毎週土日に一緒にコンテストにチャレンジしてみましょう!
(5/2,5/3にあります)