プログラミングを上達させたい

プログラミングの勉強を始めた、情報学専攻の大学院生です。モチベーション維持のため、ブログに勉強したことを書いていきます。→就職。IT全然関係ない仕事をしています

Fortranで競技プログラミング入門!(AtCoder)

この記事では、プログラミング言語Fortran」で競技プログラミングに挑む、その入り口まで案内します。色んなコンテストがありますが、ここでは「AtCoder」という日本語のサイトで行われるコンテストをターゲットに説明します。


余談ですが、僕が競技プログラミングをはじめたときは、たまたま研究室の研究で使っていた「R言語」という言語でチャレンジしました。ただ、はじめて出た大会では「標準入力で読み込んで標準出力で回答しなさい」という指定があり、大会の時間のうち半分くらいは標準入出力のやり方を検索していた、という苦い思い出があります(予習してから行けよ、という話なのですが・・・何を準備していけばよいのかも分からないくらい、ふわふわした認識でした)。
また、それ以降も継続してプログラミングコンテストに出ようとしたら「R言語」を使えるコンテストはほとんどなくて・・・結果として、再挑戦までかなり時間がかかりました。もったいない。

僕の大学の工学部(not情報学専攻)の友人たちは、数学が好きで、かつ大学1年あたりの授業でプログラミングをやった、という人もいました。しかし、競技プログラミングをやっている人が全然いなくてションボリしたのを覚えています。そしてそんな彼らが授業でやった言語というのが「Fortran」でした。

僕の「R言語」と同じく、そのときはAtCoderの対応言語にFortranは入っていませんでした。だから、専攻のメインが情報学でない彼らからしたら"わざわざ新しいプログラミング言語を勉強して競技プログラミングをはじめる"なんてのはとてもしんどいハズで、やってる人が少ないのも当然でした。一緒にやろうと誘ったこともあるのですが、実際にはじめた人はいませんでした。

ただ!!!!今!!!!国内で最も取り組みやすい競技プログラミングのサイトであるAtCoderは!!!!!!!!
Fortranにも対応している!!!!!!!!!!!!!!!!!!!

ということで、Fortran競技プログラミングに入る方法を書こうと思った次第です。

大学の授業で、とりあえず、なんとなくFortranの授業を受けているアナタ。
研究の解析でFortranを書いているけど、研究以外で使ったことないというアナタ。
そのFortran競技プログラミングの世界に飛び込んでみませんか?

就職に有利だとか色々誘い文句はありますが、何より趣味として楽しいですよ!!

さぁ、Fortranの授業で、課題を提出しちゃって暇なアナタ、今やりましょう!今!

競プロサイト AtCoderについて

僕が取り組んでいるサイトはAtCoderというサイトです。

AtCoder

・対応している言語が多い
・日本語である(本当に助かります)
・頻繁に大会が行われている=モチベーションを保ちやすい
のが特徴のサイトです。
まずはここでユーザー登録しましょう。

このサイトの使い方は大きく分けて2つです。
①リアルタイムで開催されている大会に参加する(ネットにつながっていれば、どこからでも参加可能)
②過去のコンテストの問題を解く(自分の解答が合っているかどうか判定してもらえる!!)
基本的には②で勉強を進めていって、予定的に参加できる大会があれば①参加、という感じですかね。
大会で低い順位を取るのが恥ずかしい、大会には実力を付けてから参加したい・・・という方もいるかもしれませんが、個人的には「参加できるなら参加した方がいい」と思っています。恥ずかしい、悔しい思いをするかもしれませんが、自分の客観的な評価を知ることはとても大事だと思います。
とは言っても一番大切なのは「続けること」なので、凹んだり嫌になっちゃいそうなときは参加しない方がよいと思います。
楽しみましょう!

プログラムを何で書くのか

皆さんは学校の授業や研究室などで、どのようなエディタを使ってプログラムを書いていますか?
エディタ、というのは、プログラムを書くアプリケーションのことです。
メモ帳、秀丸Terapadvimemacs・・・など、たくさん種類があります。
今回は「競技プログラミングをやってみること」がメインなので、
一旦"今まで使った中で一番使いやすいエディタ(=学校の授業で使っているもの)"を使って下さい。
※僕は「Sublime Text」というエディタを使っています。プログラムを書いた経験がない、という方がいたら、是非使ってみて下さい。

やるぞ!!第1問目だ!!!!

というわけで、とにもかくにも実際に競技プログラミングに取り組んでみましょう。
早速、記念すべき1問目です。
※僕が書いた以下の記事から問題をチョイスしています。
frfrfrfr.hatenablog.com

1問目はこの問題。
abc084.contest.atcoder.jp
問題文をゆっくり読んでみましょう。
そして、まず自分がプログラムになったつもりで(?)、解法を考えてみましょう。

問題のページの下部にいくつか、入力例というものがありますね。
入力が21 ⇒ 解答は27
入力が12 ⇒ 解答は36
となるようです。これはどのような計算で解答を出しているのでしょうか?


しかし今回は「とにかく競技プログラミングをやってみること」なので、解き方も書いちゃいます。

この問題は、「48 ー (与えられた数字)」が答えとなります。
与えられた数字が m だとしたら、文字式で言うと「48 - m」が答えです。
ちゃんと思考の途中を書くと
★残っている時間
 =(12月30日が何時間残っているか)+(12月31日まるまる)
 =(24 ー m) + 24
 =48 ー m

となります。
実際に、上の入力例2つを見てみると・・・この計算で合っていそうですね。

では早速、コードを書いて見ましょう。
とは言っても初めてなので、色々試しながら書きましょう。

書くぞ!!初解答!!!!

さてさて、お気に入りのエディタを使って、解答を書いていきましょう。
ここで、解答を書く手順ですが、
一旦必ず下記の流れでやるようにしてください。
①テンプレート(下で説明します)をエディタにペースト
②書いたら、AtCoder内の「コードテスト」で入力例を試す
③入力例に対する出力が合っていなかったら再考する

詳しく説明します。

①テンプレートをエディタにペースト
毎回ゼロから書き始めるのではなく、共通する部分などをある程度まで書いたコードを用意しておきましょう。
一旦この記事では、下記をテンプレートとしますので、下記をコピーしてエディタにペーストしてください。
書き方が自分の(授業で習った)流儀と異なっていて、かつ自分で書けそうだという方は無視しても大丈夫です。

program atcoder
  implicit none
  integer m
  read *, m    ! 変数mに、標準入力から数字を読み込み代入する

               ! このあたりに、解答を導く計算を書く

  print *,    !  ","のあとに解答となる変数を書く
end program atcoder


("!"以降のその行の文言は「コメント」と呼ばれ、プログラムには無視されます。
つまりプログラムが動作する上であってもなくても変わらない、ということになります。
じゃあいらないじゃん、と思われるかもしれませんが、後々自分が分からなくなることも結構ありますので、慣れるまでは自分が何をしているか書いた方がよいでしょう。)

さて、このコードを皆さんのエディタにペーストしてください。
では、このコードに"上書きする"形で解答を書きましょう。
さっそくですが、今回の解答を書いてしまいます。
さっきの計算だと、答えは「入力をmとすると (48 - m)」です。
コードで書いてみるとこんな感じになります。
最後は「print」して答えなければなりません。

program atcoder
  implicit none
  integer m   
  read *, m    ! 変数mに、標準入力から数字を読み込み代入する
  print *, 48 - m   ! 答えである(48 - m)を出力
end program atcoder

!これで合ってるだろうか・・・?

さてでは次へ
②書いたら、AtCoder内の「コードテスト」で入力例を試す
上記の解答コードを試してみましょう。AtCoderの問題文のページで試せます。
問題文ページの上部に「トップページ」「問題(今開いているタブ)」「提出」・・・とあるなかに「コードテスト」というタブがありますね。これを開いてください。
ここでは、問題関係なく、「このコードにこの入力例を入れたら、AtCoderのルールではこういう出力をするよ」というのを教えてもらえます。プログラムというのは環境やバージョンによって異なる動きをすることがあります。AtCoderの問題に答える際は、この「コードテスト」でチェックするのが一番よいと僕は思います。

さて、では実際にコードテストをしてみましょう。
まず、「言語」のところを「Fortran (gfortran v4.8.4)」に合わせてください。
ソースコード」の欄に、上のコードをペーストします。
最後、「標準入力」の欄には、入力例1にあった「21」を書きます。
できたら一番下の「コードをテストする」をクリック
⇒ちょっと待つ
⇒一番下の「ページをリロードする」(それでもまだの場合はもうちょい待つ)
で「標準出力」の欄にテスト結果が出てきます。
さて、このような結果が出てきたのではないでしょうか。

          27

変な空白で"27"が右に寄ってる!!!!!!!なんでだよ!!!!!

ここが標準出力のややこしいところです。めんどくさっ

さて、解決策を書きます。
左詰めで出力したいときには、下記のように書きます。

program atcoder
  implicit none
  integer m
  read *, m    ! 変数mに、標準入力から数字を読み込み代入する
  print '(i0)', 48 - m   !  "," のあとに出力したいものを書く
end program atcoder

※このサイトを参考にしました。
Fortran 入門: データ入出力


さて、これでもう一度コードテストをしてみましょう・・・

27

このように出ましたね。問題のページの「出力例」と一致しました。
では、入力例を「21」から変えましょう。入力例2の「12」を入れて、ちゃんと「36」が出てくるか試します。

・・・

できましたか?上のコードなら、ちゃんと「36」が出たかと思います。
せっかくなので、他の数字入れたりもしてください。

解答が完成したぜ!!!提出だ!!!!

「コードテスト」を繰り返した感じ、どうやら合ってそうですね・・・!
ではでは、提出してみましょう。
コードテストのページから、上部の「提出」タブを開いてください。
「問題」をA問題にセットし、言語はコードテストと同じく「Fortran (gfortran v4.8.4)」にセット。
そしてソースコードに上記の完成コードを入れて、下部の提出ボタンを押します。

・・・・

「WJ」と出ていますね。これは、チェック待ちという意味です。waiting for judgeですね。
そして、ページを更新してみましょう。どうなりましたか?
「AC」と出たでしょうか。これは「accept」の略で"正解!"という意味です。
やったね!!!!
ちなみに、他に
・WA = wrong answer = 間違っている
・TLE = Time Limit Exceeded = 時間オーバー
があります。今はピンと来ないかと思いますが、難しい問題になるとこの「TLE」に悩まされるようになります・・・!

「このコードのみが正解」というのはない

ちなみに、上記で正解(=AC)を出しましたが、他のコードでも正解となります。
例えば、以下の2つはどっちも同じくACとなります。

program atcoder
  implicit none
  integer n, m
  read *, n    ! 変数mに、標準入力から数字を読み込み代入する
  m = 48 - n
  print '(i0)', m
end program atcoder

! 変数を2つ使うバージョン
program atcoder
  implicit none
  integer m
  read *, m   ! 変数mに、標準入力から数字を読み込み代入する
  m = 48 - m
  print '(i0)', m
end program atcoder

! "print"文のところをシンプルに書くために変更しました

自分が書きやすい、分かりやすいと思うやり方でやりましょう。
極端に言えば、どんなコードであろうと、AtCoderが「AC」と言えば正解です。

終わり⇒次の問題

さて、これで一旦、「AtCoderを1問解いてみる」はクリアかと思います。
やったぜ!!!!

この記事で取り扱ったより少し計算がややこしくなりますが、次はこの問題を解いてみて下さい。

abc043.contest.atcoder.jp

※上記のコードから、計算式(「48 - m」とした部分)を変えるだけで解答できます。
※この記事のラストに、この問題の答えも書きます。自分で考えたい方はご注意ください。


以上となります。
競技プログラミング、ハマると楽しいですよ!!!!
楽しそうだな、と思った方、是非チャレンジしてみてください!

次の記事ではもうちょいFortranで色んな問題解いてみようかな。
終わり。


★次の記事(if,for文)
frfrfrfr.hatenablog.com



★最後に書いた問題の答え

program atcoder
  implicit none
  integer n
  read *, n    ! 変数mに、標準入力から数字を読み込み代入する
  print '(i0)', n * (n + 1) / 2
end program atcoder