- 辻大志郎
- 約 4,200 文字
- 3,700 View
目次
本記事は「珠玉のアドベントカレンダー記事をリバイバル公開します」企画のために、以前Qiitaに投稿した記事を一部ブラッシュアップしたものになります。
はじめに
本記事は フューチャー Advent Calendar 2018 の13日目の記事として書かれました。私は弊社に入ってから競技プログラミングなるものを知り、実際に初めてみて約1年が経ちました。競プロって何? 競プロって聞いたことはあるけれどなんだかよくわからない…という方に、競技プログラミングの面白みを少しでも伝えられたらと思い、記事を書きました。
競技プログラミングって何?
決められた条件のもとで与えられた問題、課題をプログラミングを用いて解決し、その過程や結果を競うものを競技プログラミングといいます1。
コンテストの種類
競技プログラミングといっても様々な分野のコンテストが開催されており、大きく以下の5つの分類のコンテストがあります。
(強くなるためのプログラミング -様々なプログラミングコンテストとそのはじめ方- より引用)
Kaggleのようなデータ分析のコンテストは上記の表でいうと「データマイニング」に該当し、ISUCONのようなコンテストは「サーバインフラ」のようなコンテスト、SECCONのようなコンテストは「セキュリティ」のコンテスト、CodinGameのようなコンテストは「ゲームAI」のコンテストに該当するでしょう。私が参加しているのは、いわゆる「アルゴリズム」のコンテストに該当します。「アルゴリズム」のコンテストは1回あたりにかかる所要時間が比較的短く、参加しやすいという特徴があります。
アルゴリズム系のコンテスト
「アルゴリズム」に分類されるコンテストは国内外で様々に開催されています。「アルゴリズム」の中でも1日あるいは数日かかって開催される「マラソン」という形式のコンテストも存在しますが、ここでは詳しくは触れません。なお、弊社で過去何回か行われている 「HACK TO THE FUTURE 2」はマラソン形式のコンテストでした。
以下のようなサイトでコンテストは開催されています。おすすめは AtCoder です!
- AtCoder
- Codeforces
- Topcoder
- LeetCode
- HackerRank
- …(他多数)
詳細は 競技プログラミング を参照ください。
なぜ競技プログラミングは面白い?
コンテストにおいて、多数の参加者と自身のプログラミングの実力を比べることになります。問題解決やプログラミングが好きで、そして誰かと競い合うことが好きであれば、競技プログラミングは面白いと感じるでしょう。
ここでは AtCoder のコンテストに掲載された実際の問題をいくつか見てみましょう。
CODE THANKS FESTIVAL 2018:Colored Balls
(実行時間制限: 2 sec / メモリ制限: 1024 MB)
初め箱には赤い玉が
個、青い玉が 個入っています。
高橋君は以下の操作を繰り返して、箱を空にしたいです。
・ 赤い玉を個、青い玉を 個箱から取り出す。
もしくは、
・ 赤い玉を個、青い玉を 個箱から取り出す。
各操作ではこのつのいずれか好きな方を行うことができ、毎回同じ操作を行う必要はありません。
高橋君のために、箱を空にする方法があるかどうか判定してください。箱を空にすることができる場合は Yes を、できない場合は No を出力せよ。
簡単な問題の例をあげてみました。
これは「赤い玉を
Yes そうでない場合は No となります。
import java.util.Scanner; |
もう少し難しい問題を見てみましょう。いわゆる「あみだくじ」の問題です。
問題の題材としては NewsPicksでも取り上げられており、シンプルですが面白い問題です。
AtCoder Beginner Contest 013 D 阿弥陀
(実行時間制限: 4 sec / メモリ制限: 256 MB)
古くより伝わる日本の伝統的なくじ引き、あみだくじをご存知だろうか?
あみだくじを行うときは、まず本の平行な縦線を引く。次に、 本の横線をその中に引いていく。それぞれの横線は隣り合う 本の縦線を結ぶように引かなければならず、 本以上の横線がまったく同じ高さにあってはいけない。ここでは、上から 番目にある横線が、左から 番目の縦線と 番目の縦線を結んでいるとしよう。 の場合のあみだくじを以下に示す。くじを引くときは、縦線を 本選び、その上端から線を下っていく。途中で横線に遭遇したときには必ず曲がらなければならず、また縦線を上向きに辿ってはいけない。たとえばこのあみだくじで左から 番目の縦線から始めてくじを引くと、左から 番目の縦線に辿り着く。
さて、ここまでは普通のあみだくじであるが、何かにつけビッグデータという言葉が騒がれる昨今である。あみだくじがこれから先生きのこるためには、あみだくじもビッグになってビッグデータに対抗していかなければならない。
そこで、あみだくじを縦に個つなげることで巨大なあみだくじを作ることを考えよう。たとえば、先ほど例に挙げたあみだくじを 個つなげてみると以下のようになる。この場合、左から 番目の縦線から始めてくじを引くと、辿り着く場所は左から 番目の縦線になる。
こうして作った巨大あみだくじだが、あみだくじ本来の目的を果たせなければビッグになった意味もない。つまり、この巨大なあみだくじを使ってくじを引いた結果がどうなるかを効率よく計算できなければ、せっかく作った巨大あみだくじもただの落書きである。
そこで、を満たすすべての整数 に対し、巨大あみだくじの左から 番目の縦線を選んで線を辿っていったとき、最終的に下端で左から何番目の縦線に行き着くかを計算するプログラムを書いて欲しい。 制約
与えられている問題文が少し長いですが、いわゆる「あみだくじ」を実施したときにどこからどこにたどりつくか、を求める問題です。あみだくじが
(i)
まずは一番簡単な
これは計算量
import java.util.Scanner; |
次に
(ii)
問題文で与えられている例であれば…
となります。
さて、
import java.util.Scanner; |
さて、もともと与えられていた制約は…
制約
(実行時間制限: 4 sec / メモリ制限: 256 MB)
でした。(ii) の実装の場合、計算量は
(iii)
(ii) のような、あみだくじの結果を
このように考えると
このようにしてあらかじめ
また、
あみだくじを
全体の計算量
import java.util.Scanner; |
何を学べる?
アルゴリズムの基礎を学べる
問題を解くにあたっては、基本的なアルゴリズムを理解し、具体的な問題に応用できるスキルが求められます。
競技プログラミングを取り組みながら、以下の内容を学べます。
(高度な内容は除いています)
- 計算量の概念
- データ構造
- 再帰
- 全探索・幅優先探索・深さ優先探索・bit全探索
- グラフ
- 動的計画法
問題解決の方法を学べる
問題を解くにあたっては、以下のような流れで進めることが一般的です。
問題を読む
上記の中で特に重要なのは 考察する ということです。解答の方針が決まらないまま実装しても、いたずらに時間を費やすだけで解が得られないことが多いです。考察の過程で「どのようにしたら問題を解くことができるか」を考えることが求められます。競技プログラミングを通じて、問題解決の方法を学べます。
おわりに
具体的な問題例を通じて、競技プログラミングの基本的な紹介と、その面白みを伝えることを試みました。競技プログラミングの面白さが、少しでもみなさんに伝わればと思います!