freeeの開発情報ポータルサイト

社内プログラミングコンテストを開催しました

はじめに

こんにちは、freee 競技プログラミング部副部長のです。普段は認証認可周りの開発をしています。
好きなアルゴリズムは Rabin-Karp Algorithm、好きなデータ構造は Union-Find、好きな定理は Spectral 定理です。

先日 freee 初の社内プログラミングコンテストを開催しました! 今回は、開催までの苦難やコンテスト当日の様子をご紹介したいと思います。

最後に重大告知もあるのでぜひ見てください!

社内プログラミングコンテスト開催するぞ!

日経さんの社内プログラミングコンテスト(社内プロコン)の記事を読み、リモート下になって減っていたチーム外の人との交流のために社内プロコンを開催するのは良さそう、ついでに部員募集という意味でもいい宣伝になりそうという思いから社内プロコンを開催することになりました。

また部員から「社内プロコンを開催するなら freee のドメイン知識を絡めた問題を出したい」との声も上がり、作問にも挑戦してみることになりました。 運営メンバーに作問経験者がいないのに思い切った決断をしたなと今になって思います。

オンラインジャッジシステムの準備

自作問題を公開できるサイトはいくつかありますが、freee のドメイン知識を絡めた問題を社外のデータベースに保存するのは躊躇われたため、自分たちでコンテスト用のオンラインジャッジシステム構築をすることにしました。

幸い、いくつかのオンラインジャッジシステムが OSS として公開されており、その中でも対応言語の多さと操作性のわかりやすさから DMOJ という Django 製のオンラインジャッジを使うことにしました。 DMOJ 自体は普段からコンテストを開催しているサービスなようで、そこで使われているコードを OSS として公開していただけているようです。

ただし、自前で動かす際の注意として「このサイト以外で動かすことを想定していないからスムーズにインストールできることはほとんどないよ」とあるように、環境構築には難儀しました。

The DMOJ site was never written in such a way as to be run elsewhere than on this site, so installation is almost never smooth. https://dmoj.ca/about/clones/

Django を使ったことなかったのでそこから軽く勉強し、コンテナ化されてないのでコンテナ化して・・・と時間はかかりましたがどうにかコンテスト開催までには間に合わせることができました。

作問

作問はコンテスト準備における最大の難関パートでした。 普段の部活動は週末にある AtCoder のコンテストの感想戦が主でしたが、コンテスト前の数週間の部活動はほぼ作問の相談に費やしていました。

当日出した問題を1問紹介すると次のような問題を出題しました。


閏年判定

問題

実行時間制限: 2 sec / メモリ制限: 512 MB

西暦  N 年が閏年なら Yes、平年ならば No を出力してください。

制約
  •  1 \leq N \leq 10^{4 \times 10^{7}}
  • 入力は全て整数

想定解は  N の下4桁だけを使って閏年判定するです。 出題意図としては、よくみる閏年判定のような問題でも、制約によっては今までとは違うアプローチが要求されることもあるということを知ってもらいたくて出題しました。ちなみに入力の桁数が  O\left(10^{6}\right) 程度だと Ruby や Python などの多倍長整数を気軽に扱える言語では工夫なく解けてしまったため、それらの言語でも工夫を余儀なくされる制約にするために桁数を増やしました。

以上の問題を含め最終的には全6問作問しました。典型問題を少しいじった程度の問題しか出せませんでしたが、それでも曖昧さのない問題文を考えたり、嘘解法1を落とすテストケースを作成するのはなかなかに骨の折れる作業でした。 自分が作った問題だとついつい理想的なプログラムだけを想定してしまい嘘解法まで気が回りませんでしたが、レビューで指摘されて「それは考慮に入れられてなかったなぁ」ということが多々ありました。 このようなエッジケースを考慮することは実務でも役に立ちそうなので今後洞察力を磨いていきたいところです。

今回自分たちで作問したおかげで毎週凝った問題でコンテストを開催している AtCoder がいかに凄いのかを身を持って体感することができました。

コンテスト当日

当日はエンジニアの競技プログラミング未経験者だけでなく、普段仕事ではプログラミングをしていないであろうビジネス職の方にも参加していただけました! またリアルタイムでは参加できなかったけれども後日バーチャルコンテストとして楽しんでおられる方もおり、想定していたよりも多くの方に楽しんでいただけました。

コンテスト中、運営側は基本的に暇だったので順位表を眺めながら雑談をしていましたが、順位表を眺めているだけでも各参加者の戦略が見えて結構面白かったです。 特に閏年判定の問題は競技プログラミング経験者は鍛えられた嗅覚により危険な匂いを察知したのか解かずに次の問題に移るという戦略をとっていたのは印象的でした。一見簡単そうな問題でも制約を見て捨てるという決断ができるのはさすが経験者だなと妙に納得していました。

当日のコンテストランキング表
当日のコンテストランキング表の一部. 難易度の見積もり・制限時間・問題数をどうするかは今後の課題

コンテスト終了後は問題の解説を行いました。想定解の説明のみならず、想定解を思いつくにはどうしたら良かったのか、うまく通せなかった方のアプローチは何がいけなかったのか等の議論をすることができ競プロ仕草の一端を伝えられたのかなと思います。

コンテストに参加していなかった人に感想を共有している様子を観測できたり、コンテストが終わったあとも解けなかった問題を考えて正解に至っている方などおり、結構楽しんでいただけたようです。 開催して良かったと思います。

おわりに

以上、社内プログラミングコンテストのご紹介でした。 やってみてそれなりの手応えを感じたのでまた折をみて開催してみたいと思っています。

最後に重大告知!弊社が主催の freee プログラミングコンテスト2022(AtCoder Beginner Contest 264) が 2022/8/13 に行われます!ぜひご参加ください!!!2


  1. 嘘解法: ジャッジシステムのテストケースは全て通るがロジックとしては間違っている解法。テストケースが弱いと正解判定になってしまう。

  2. 問題は AtCoder 社の方々が作られています