2019年10月18日金曜日

Ruby で競技プログラミングを始める方法 (Codeforces 編)

概要

Codeforces という Telegram 社が進める競技プログラミングサービスの使い方を紹介します
アカウント登録から実際にコンテストに参加してコードをサブミットするところまで紹介します

環境

  • macOS 10.15
  • Ruby 2.0.0p645

ユーザ登録

まずはユーザ登録します
トップページにアクセスして右上の「Register」を選択します

ハンドルネームとメールアドレス、パスワードを入力します
「Register」ボタンを押すと確認のメールが届きます

メールに記載されているアドレスをクリックすれば登録完了です

トップページの右上の「Enter」からログインできることを確認しましょう

参加したいコンテスト確認

上部のメニューに「Calendar」があるのでそれを使うのが簡単です
コンテストがいつ開催されるのかひと目でわかります

参加したいコンテストをクリックすれば開催の時間や内容が確認できます
コンテストにはいろいろな種類があります
基本は 2 時間で終わる「Codeforces Round」をやるとい良いかなと思います
Div1 から Div3 でレイティングによって参加可能なコンテストも分かれています
その他にも数週間かけて行うコンテストや言語が限定されているコンテストなどもあります

コンテスト登録

参加したいコンテストが見つかったらまずは登録しましょう
写真は登録開始前の写真になります
登録可能な状態になると一番右の部分に「Register」ボタンが表示されるので登録しましょう

そして実際にコンテストが始まるとコンテストに入ることができるようになり問題を確認することができるようになります

コンテスト開始、コードサブミット

問題は基本英語です
日本語はありません
もともとはロシア語だったので英語があるだけでもありがたいです

画面下のほうにいくとコードをサブミットできるフォームがあります
自分の進め方としてはローカルで開発をして問題がなければそれをサブミットする感じです
ファイルは 1 つしかサブミットできないので class などをわける場合も 1 つのファイルにまとめましょう

また直接コーディングしてサブミットすることもできます
自分は好きなエディタで開発してからサブミットしたいのでこれは使ったことがありません (Submit Code タブ)

サブミットしたコードの結果は「My Submissions」で確認できます
Verdict が「Accepted」になればすべての問題が解けたことなります
問題文中にサンプルの解答があるのですが実際はそれ以外にも問題がありそれらはどんな入力でどんな出力になれば良いかはわかりません
なので途中でコケた場合は何かしらの実装漏れがあることになります

その他の機能

  • Status
    • コンテストに参加している全ユーザの進捗と開発言語が確認できます
  • Hacks
    • 自分は使ったことがないのですが一定の条件をクリアすると他の人のコードを見ることができる機能らしいです (?)

過去問も解ける

過去に行われたコンテストはすべて過去問として公開されています
もし解けてもレイティングは上がりませんが練習したい場合や本番のコンテストで解けなかった問題に再度挑戦したい場合に使えます

またコンテストが終了して過去問になるとそのコンテストにサブミットされたすべてのコードを確認することができます (Status タブ)

アカウントページから過去に参加したコンテストの履歴が見れる

右上のアカウント名をクリックすると自分が過去に参加したコンテストやサブミットしたコードの一覧と結果を確認することができます

画像はアカウントのページから「Submissions」タブでサブミットしたコードの一覧を確認しています

注意事項

  • Codeforces 上で実行される Ruby のバージョンが 2.0.0 にしか対応していない
    • ローカルでは 2.6 など最新のバージョンを使っている場合、Codeforces にサブミットするとエラーになる場合がある
    • 自分は rbenv を使ってローカルでも Codeforces と同じ Ruby のバージョンが使えるようにしている (参考)
  • gem は使えない
    • 使えるのは標準ライブラリだけです
    • gem install したライブラリは Codeforces 上では使えません
  • Web アプリやライブラリを作りたい人には向かないかも
    • 基本はアルゴリズムを鍛えたい、勉強したい人向けの問題になります
    • Class や Module を使ってツールを作る感じではないのでそういうことをしたい人には向かないかもしれません

Tips

  • 問題は基本的に標準入力を受け取るので標準入力の扱い方をマスタしておきましょう

  • スペース区切りの 2 つの標準入力の数値をそれぞれの変数に格納

vals = STDIN.readlines
n, m = vals[0].split(' ').map(&:to_i)
  • 1 行目はスペース区切りの数値で 2 行目はスペース区切りの数値を配列として格納
vals = STDIN.readlines
h, w = vals[0].split(' ').map(&:to_i)
hary = vals[1].split(' ').map(&:to_i)
  • 1 行目で受け取った数値分の配列が入力される場合
vals = STDIN.readlines
n = vals[0].to_i
stones = []
n.times { |i|
  s = vals[i + 1].split(' ').map(&:to_i)
  stones.push(s)
}

0 件のコメント:

コメントを投稿