SaaSで競技プログラミングは役に立つのか？



# はじめに

こんにちは。株式会社HRBrainで内定者インターンに参加しているNubです。

私は趣味で競技プログラミングをしており、自作ライブラリをGo言語で書いていたりしています。
採用選考で「競技プログラミングやってます」や「自分だけのニーズを叶える開発してます」等をアピールして採用していただきました。（もちろん他のことも沢山アピってます）

「じゃあ、競技プログラミングやってる人間がSaaS系の会社に入ってどう？」を反省を含めて記事にしたいなと思い、本記事では「SaaSで競技プログラミングは役に立つか・それ以外で何が必要なのか」というテーマで書いていこうと思います。

本記事は[HRBrain Advent Calendar 2023](https://qiita.com/advent-calendar/2023/hrbrain) 19日目の記事です。

## （保険）あなたは「強い」の？

**「弱い」です。**

私はAtCoder（後述）というサービスで茶色コーダーの存在です。

https://atcoder.jp/users/lazi

[AtCoder社長のchokudaiさんのブログ](https://chokudai.hatenablog.com/entry/2019/02/11/155904)では、AtCoderでの茶色は「現役学生で多少優秀なレベル」という位置づけです。

# （ざっくりとした）結論

競技プログラミングで得られる（得やすい）ものは

- プログラムを書くことが出来ること
- 決まった入力と出力に1からコードが書けること

得られない（得にくい）ものは

- 集団で協調してプログラムを書く経験
- インフラやフロントを含めて全体で1つのものを作る経験
- ソフトウェア設計の思想等
  
だと思います。

# 競技プログラミングとは

まず競技プログラミングについて簡単に紹介すると、[Wikipedia](https://ja.wikipedia.org/wiki/%E7%AB%B6%E6%8A%80%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)では以下のように述べられています。
> 競技プログラミング（きょうぎ - 、英: Competitive programming、略称: 競プロ）とは、プログラミングコンテストで行われる競技の一種である。
> （中略）
> 競技プログラミングでは、参加者全員に同一の課題が出題され、より早く与えられた要求を満足するプログラムを正確に記述することを競う。

簡単に言えば「問題を出すから、解くためのプログラムをなるはやで書いて出してね」というゲームです。

## AtCoderとは

AtCoderはそうした競技プログラミングのサービスの1つです。

最近は登録者数が増えて全世界で50万人のユーザを持っています。
ユーザが競技プログラミングという側面でどの位置づけなのかをレーティング及び対応した色で判別されており、茶色コーダー（レーティングが400 ~ 799）は下から数えて2番めですが、上位30%の位置です。

https://prtimes.jp/main/html/rd/p/000000038.000028415.html

https://gogocatslife.com/20220619atcoderhist/

## どんな問題が出されるのか

私はよくAtCoderというサービスで開催されているコンテストに参加しているので、AtCoderの問題を例に出します。

> 問題文
>
> N 人の人 $1,2,…,N$ がある試験を受け、人$i$ は $A_i$ 点を取りました。
> この試験では、$L$ 点以上を取った人のみが合格となります。
> $N$ 人のうち何人が合格したか求めてください。
>
> 制約
>
> 入力は全て整数
> $1 \leq N \leq 100$
> $1 \leq L \leq 1000$
> $0 \leq A_i \leq 1000$
>
> 入力
>
> 入力は以下の形式で標準入力から与えられる。
> $N \ L$
> $A_1 \ A_2 \ ... \ A_N$
>
> 出力
> 答えを整数として出力せよ。
>
> 入力例1
>
> 5 60
> 60 20 100 90 40
>
> 出力例1
> 3

https://atcoder.jp/contests/abc330/tasks/abc330_a

## 解答例

この問題の解き方は簡単で、$A_i$を全てチェックし、$L$以上の要素をカウントするだけです。

HRBrainではGo言語を使ってサービスを開発しているため、AtCoderでもGo言語を使っています。
解答例として、こんな感じのコードを書いて提出すればよいです。

```go
package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    var N, L int
    fmt.Scan(&N, &L)

    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()

    A := make([]int, 0, N)
    for _, s := range strings.Split(scanner.Text(), " ") {
        ai, _ := strconv.Atoi(s)
        A = append(A, ai)
    }

    ans := solve(N, L, A)
    fmt.Println(ans)

}

func solve(N, L int, A []int) int {
    var ans int

    for i := 0; i < N; i++ {
        if A[i] >= L {
            ans++
        }
    }

    return ans
}
```

https://atcoder.jp/contests/abc330/submissions/48207082

# 競技プログラミングで得られるもの・得られないもの

競技プログラミングでは、問題を解く上で重要でない部分をなるべく削減する努力がなされているため、ユーザは問題を解くアルゴリズムを考える作業に没頭できます。

## 競技プログラミングで得られるもの

競技プログラミングで得られるものとして、2点挙げられると思います。

1. 基本的な構文・標準ライブラリを使った **「実装力」**
2. 効率的に処理するにはどうすればよいかを考える **「数学的・論理的思考力」**

### 実装力

**「実装力」** は、問題を解く上でほぼ必ず培われるスキルだと考えています。
現に、私は半年でGo言語の基本的な構文が書けるようになり、AtCoderでメイン言語として扱うことが出来、インターン中の開発タスクでも特に問題ない状況です。
（インターンレベルの少ない稼働で完遂可能なタスクが当たっているという話もありますが）

### 数学的・論理的思考力

**「数学的・論理的思考力」** は、上位の問題になるにつれて、より複雑なプログラムや効率的なアルゴリズムを構築しなければならなくなります。
そのため、「こういう問題と入力が与えられた時、〜を使って処理をすれば効率良く処理出来る」という思考を頻繁に行うため、自然と考えられる様になりやすくなると思います。

実際に、

- [パナソニックグループがAtCoderユーザーに伝えたいこと](https://recruit.jpn.panasonic.com/AtCoder/)
- [天才プログラマー2人が語る、高度IT人材の採用のポイントとは？](https://dentsu-ho.com/articles/7074)
- [なぜトヨタ自動車がAtCoderメンバーを必要としているのか](https://atcoder.jp/contests/abc270)

を見ると、AIの開発・チューニングや最適化等で素養を見出しやすい競技プログラマに焦点が当たっている印象です。

## 競技プログラミングで得られないもの

得られないものとして、5点あると思います。

1. 標準入力以外のデータの受け取り
2. データベースやフロントとの連携
3. 不明な要件が存在する場合の対処
4. 集団で1つのものを作る経験
5. ソフトウェアの開発技法・設計等

### 標準入力以外のデータの受け取り

AtCoderを含めて、競技プログラミングのサービスでは一般的に標準入出力を使ってデータの受け取り・解答データの出力を行います。
更に、与えられる入力は簡単のため半角スペースである場合が多いイメージです。そして、その入力は正しい入力です。

例えばインターネット経由で情報の受け渡しをする場合、JSON等のデータ記述言語を使ってデータの受け渡しをする場面があると思いますが、競技プログラミングでこういった形式をあまり見たことがありません。

また、「得たデータは本当に正しいのか」というチェックをする必要がありません。
SaaS等を含めて、個人情報と紐づいたデータを扱う場合は「正しいユーザから正しい入力（リクエスト）が送られてきたのか？」をチェックしなければならず、そのヌケモレを突かれ「見れないはずのデータが見れる」という話が度々聞こえます。

趣旨と離れますが、正しい挙動をしていそうなプログラムに撃墜ケースを与える（Hackする）ことが出来るサービスに[CodeForces](https://codeforces.com/)があります。
私はやったことが無いのですが、機会があったらやってみたいと思います。

### データベースやフロントとの連携

AtCoder等の競技プログラミングサイトでは、1つのファイルで全てを処理するプログラムを提出します。
さらに、[標準入力以外のデータの受け取り](#標準入力以外のデータの受け取り)で述べたように、標準入力で与えられるデータ以外に依存するデータはありません。

そのため、SaaSの開発現場でありがちの

- データベースから〜の情報を取ってきて、それを使って処理をする
- ブラウザ等に渡していい感じに見せる

といった、複数のレイヤーを組み合わせて何かを実現する経験がありません。
さらに、標準でないライブラリを使って何か機能を作ることや、競技プログラミングで使わないライブラリ等の知識が少なかったりします。

データベースの操作を(SQL)対象としたサービスに[TOPSIC SQL CONTEST](https://topsic-contest.jp/)があるため、絶対にそうとは言い切れませんが、経験としては不足しがちな印象です。

### 不明な要件が存在する場合の対処

競技プログラミングでは参加者全員に問題を与えますし、入力や想定解が明確に示されています。要件にヌケモレが無いということです。

ですが、開発現場でタスクを進めているうちに「こういうケースはどうしますか？」といった気持ちを抱くときがあります。見えざる要件が見えた瞬間です。

開発現場で楽しい（苦しい？）場面ですが、こういったケースに当たって詰めていく経験もあまりないです。

### 集団で１つのモノを解く経験

**これめっちゃデカいです（笑）**

基本的に、多くの競技プログラミングサービスでは解答者は自分1人です。（利用規約で縛られている場合もあります）ICPCやISUCON等ならグループ開発する環境があるのですが、皆で集まって作る経験は結構大事な印象です。

自分は大学での研究を含めてほぼ個人開発でした。（大学のグループ開発課題で半分以上実装してしまう罪業あり）
そのため、コードレビューをしていただく機会やペアプログラミング等々をやらせていただき、「協力して1つのモノを作るってこういう感じなんだ」を今更感じています。本当に「強い」人たちからのフィードバックは、すごくありがたいことです。（伝える自分は拙い）

また、他人が見落としていた部分を付け加えるといった経験（持ちつ持たれつ？）といったことも不足しがちです。採用の現場を含め、「グループ開発したことありますか」と聞かれるのは、この辺を重要視しているからなのかなと思っています。協調して作る経験は、今後エンジニアとして活動する上で非常に大事だと思います。

### ソフトウェアの開発技法・設計等

**これ「も」めっちゃデカいです（笑）**

競技プログラミングでは「早く回答できることが命」なため、オレオレ開発によって作成された自作ライブラリが蔓延っており、「俺だけが読めるプログラム」が割とあります。

例えば、

- ネストが深すぎる（11次元ループとか）
- linterを使ってない（異様な空白 or スペースのないギチギチに詰まったコード）
- 実装に失敗したであろう大量のコメント
- main関数ベタ貼り（関数にジャンプして遅延することを防ぐ）
- マクロの多用（別の言語と化している）
- 変数をアルファベット1文字で宣言し、問題の入力と対応していない / 変数の意味が分からない（アセンブラ？）

などがあります。開発現場では発狂モノだと思います。

競技プログラマは分かっててやってる節があるので仕方のない話かもしれませんが、強い / 弱いに限らずコードを見に行くとこういったものをよく見るので、勉強しにくいなという印象です。

また、1ファイルで提出する形式のサービスが多いため、パッケージを分けて開発することが出来ず、クラスやinterface等の切り分けが面倒くさいです。
競技プログラミングにまで〜駆動設計を持ち込むわけではありませんが、全体的に責任範囲を分離しにくく、可読性も低くなりがちな印象です。

# まとめ

競技プログラミングで得られるものは、

1. 基本的な実装能力
2. 「効率的に処理をするにはどうすればよいか」を考える論理的思考力

が挙げられます。これは

- まず「プログラムを書ける」というスタートラインを保証する
- 決まった要件とわかりやすい入力・出力結果に対して、効率を気にして開発できる

という面で役に立ちます。

得られないものとして、

1. 標準入力以外のデータの受け取り
2. データベースやフロントとの連携
3. 不明な要件が存在する場合の対処
4. 集団で1つのものを作る経験
5. ソフトウェアの開発技法・設計等

があり、これは

- 色々な入力形式を知っていく必要がある
- 複数のレイヤーを組み合わせて作る経験をした方が良い
- コミュニケーションを取って、要件を精緻化する必要がある
- 協調してプログラムを書けるようになる必要がある
- 様々な設計思想を知って、品質の高いプロダクトを作っていかなくてはならない

という示唆があると思いました。

今後勉強していくことが多くて、慌てて勉強しています。

# PR

株式会社HRBrainでは新しいメンバーを募集しています。
中途採用・新卒3期生を積極募集中です。

https://www.hrbrain.co.jp/recruit