私が技術者面接のコーディング試験で出している(いた)問題

私は会社で技術者の面接を行っているのですが、実際に開発者の採用試験で出している(出していた)、コーディング実技試験の問題を紹介します。

# 試験の形式

面接試験はビデオチャットの形式で行うことが多いので、応募者のPC内でコードを実行できる環境を起動してもらい、それを画面共有で見せてもらっています。

他の会社の試験では1問90〜200分程度で行う場合もあるようですが、私は1問15分程度の比較的軽めの問題を数問書いていただく場合が多いです。

Copilot 等の生成AIは使用禁止、Web検索も禁止で、シンタックスや言語仕様等の不明点は口頭で面接官(私)に聞いてもらう、というルールで行っています。

なお、変数名の付け方やコードの美しさ・短さ等は、私は試験では一切考慮しません。

# 歴史的変遷
コロナ禍以前は、会社に実際に来てもらっての面接が多かったため、開発環境としては会社側で用意したPCを使ってもらうことが多かったです。

面接時にPCを持ち歩く人は少なかったですし、コーディング試験をやるためだけに PC 持参のお願いをするのも申し訳なかったためです。

使い慣れていない環境でコーディングをしてもらうため、出題する私の方でもかなり遠慮していました。

現在は、コロナ禍がありリモート面接が当たり前になったので、コーディング試験はかなりやりやすくなりました。普段使い慣れた開発環境をお使いいただけるので、出題側の遠慮も無くなりました。


# 1. フィボナッチ数列

## 問題
```
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ... という数列(フィボナッチ数列)を
100個目まで表示するプログラムを書いてください。
```

## 解説
フィボナッチ数列の問題は比較的よく出しています。Python の [functools のドキュメント](https://docs.python.org/ja/3/library/functools.html) にコードがそのまま書いてありますので、使ったことがある方はすぐ書けると思います。

解き方がいろいろありますが、解き方によって評価が変わることはありません。
ただ、コミュニケーションの中で「では次は再帰で書いてみてください」みたいな流れになることはあります。

回答の傾向としては、

- 変数(3つ)をforループで回す方: 45%
- リストの末尾に push していく方: 50%
- 再帰で書かれる方: 5%

といった感じです(体感)

ちなみに、社内でこの試験の話をしていたら、JSを書くデザイナーも面白がって書いてくれたりしましたし、エクセルでも解けると思いますので、この試験は全職種にやってもいいんじゃないかと思っています。

# 2. 関数を返す関数

## 問題

```
次のように動作する関数 adder を作ってください

>>> a = adder(10)
>>> a(3)
13
>>> a(8)
18
```

## 解説

題名に「関数を返す関数」とあればわかりやすいですが、実際の試験ではそのような言い方はしていません。

フロントでJS系を書かれている方、特に React や Flutter を書かれている方は較的簡単に書けると思います。
また、Python でデコレーターを書かれたことがあれば問題無いはずです。
PHP では書けないため、PHP で試験をされる方には出題しません。

書く時に少し悩まれるようであれば、「adder の返り値(a)の型は何だと思いますか」という質問をします。

そこで、「整数を引数にとり整数を返す関数」という型がわかれば、あとは順序立てて書いていけると思います。


# 3. Maximum Subarray (LeetCode #53)
LeetCode から、いくつか出す場合があります。

https://leetcode.com/problems/maximum-subarray/

## 問題

与えられた整数の配列 ( nums ) の中から、連続する一部(subarray)を取り出して
合計した際に最大となる部分の合計値を取得しなさい。

Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6

Explanation: The subarray [4,-1,2,1] has the largest sum 6.

## 解説

ループが理解できていれば難しく無いと思います。
愚直に、二重にループするで良いでしょう。

なお python の [itertools.combinations_with_replacement](https://docs.python.org/ja/3/library/itertools.html#itertools.combinations_with_replacement) を知っていれば1行で書けます。

# 4. Spiral Matrix (LeetCode #54)

https://leetcode.com/problems/spiral-matrix/

## 問題

図([リンク先参照](https://leetcode.com/problems/spiral-matrix/))で示している通り、二次元の表の各要素を、渦を巻くような順番で表示しなさい。

## 解説

面白い問題ではありますが、ひらめき力が求められますし、ある程度解き方が思いついても書き上げるまで30分程度かかってしまうので、試験としてはあまり有用ではありませんでした。

この問題が試験で出てきた時、詰まらずに書ききれる方は本当に優秀な方だと思います。

「表自体を回転させる」という解き方がひらめけば、あとは中級レベルのコーディング力があれば比較的容易に解けると思います。

ちなみに私は、最初にこの問題に取り組んだ時は「表を回転させる」という発想がなかったので、愚直に「カーソルをつきあたるまで右に進めて…つきあたったら進行方向を90度変えて…」といった冗長なコードになってしまいました。

# その他の高難易度課題

一時期、社内の開発者と採用方針を検討していた時に、「高難度課題を出して、解き方を口頭で応えてもらう」という形態をとったことがあります。

コロナ禍前で、会社に来社してもらった応募者に、時間をかけずに技術レベルを深く測定できると思ったためです。

ただ、やってみたところ、私は非常に苦手だと思いました。実際に動くコードでないと評価が難しかったです。

## N-Queens (LeetCode #51)

https://leetcode.com/problems/n-queens/

比較的有名な問題だと思います。ルールが明快なので、出題がやりやすいです。
私ではない、社内の開発者は、前職の試験で実際に面接試験で出たそうです。

難易度が高く、解き方がわかっても初見だと書き切るのに1時間近くかかると思いますので、面接試験で行うのはなかなかハードルが高いです。

かといって、考え方だけのインタビューだけで技術力を図るのは、面接官側の特殊技術が必要です。私は難しいと思いました。

ただ、トレーニングとして解いておくことは大事だと思います。
当社でも、若手社員のトレーニングとして社内勉強会でみんなで書いたりしました。

また、応用情報技術者試験の過去問でも出てきてたと思います。

[itertools.permutations](https://docs.python.org/ja/3/library/itertools.html#itertools.permutations) を使うと比較的書きやすいかなと思います。

## The Skyline Probrem (LeetCode #218)

https://leetcode.com/problems/the-skyline-problem/

当社ではこのように訳した文章を使いました。

### 都市の稜線
都市の稜線とは、遠くから見たときにその都市のすべての建物によって形成されるシルエットの輪郭です。都市の景観写真（図A）に示されているようにすべての建物の位置と高さが与えられているとします。これらの建物によって形成された稜線をまとめて出力するプログラムを作成します（図B）。

[[図](https://leetcode.com/problems/the-skyline-problem/)]

各建物の座標情報は整数の三重項 `[Li, Ri, Hi]`, ここで、 `Li` と `Ri` はそれぞれi番目の建物の左端と右端のx座標で、`Hi` はその高さです。

`0 ≤ Li`, `Ri ≤ INT_MAX`, `0 < Hi ≤ INT_MAX`, そして `Ri - Li > 0` であることが保証されています。 
すべての建物が、高さ0で水平な面に接している完全な長方形であるとします。

例えば、図Aのすべての建物の寸法は、 `[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]` として記録されます。

出力は、都市の稜線を一意に定義する `[ [x1,y1], [x2, y2], [x3, y3], ... ]` 形式のキーポイント （図Bの赤い点）のリストです。キーポイントは、水平線分の左端です。一番右の建物が終わる最後のキーポイントは、単に稜線の終端を示すために使用され、常に高さはゼロです。また、隣接する2つの建物間の地面も稜線の輪郭の一部と見なす必要があります。

例えば、図Bの稜線は、`[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]` となります 。

#### 補足:
建物の数は、`[0, 10000]` の範囲内であることが保証されています。
入力リストは、左のx位置Liで昇順にソートされています。
出力リストはx位置でソートする必要があります。
出力稜線に同じ高さの連続する水平線があってはいけません。たとえば、 `[...[2 3], [4 5], [7 5], [11 5], [12 7]...]` は受け入れられません。最後の出力では、高さ5の3行を1つにまとめる必要があります。`[...[2 3], [4 5], [12 7], ...]`

### 解説

問題としてはよくできており、傑作だと思ってはいますが、難解です。

まず問題を理解するのに10分ぐらいかかります。
また、解き方の方針がわかっても、実際に書くと初見だと1時間近くかかると思います。

この問題も、コロナ禍前の面接で、問題だけ見てもらって解き方をヒアリングするという試験を行いました。

N-Queens と同様に、ヒアリングだけで行うと面接官側の高い技術が必要で、私はその技術が十分に無いためあまりいい試験にはなりませんでした。

なお、こちらも、若手社員のトレーニングとして社内勉強会でみんなで書きました。


# まとめ

こういった課題を素早く解くために、 [itertools](https://docs.python.org/ja/3/library/itertools.html), [functools](https://docs.python.org/ja/3/library/functools.html) はよく練習しておいたほうが良いと思います。