LINEの新卒採用試験ズバリ問題解説 〜2021年開発コース(実装問題)版〜

はい、みなさんこんにちは。

3月7日にオンラインで開催した「LINE Engineer Meetup for Students」にて、2021年の新卒採用開発コース向けに出題している問題の傾向や解くためのコツなどを学生の皆様に解説させていただきました。

はじめにお断りをさせていただきますが、本エントリで対象にしているJob categoryは技術職の開発エンジニアとなります。他の職種の試験内容についての言及はしませんので予めご承知おきください。

今回の記事では、当日使用したスライドを元にして、LINEの本採用での問題の傾向や解くためのコツなどを解説させていただこうと思います。
実際に出題したことがある問題を利用して解説しますので、より実践的な解説記事になっているかと思います。
本記事の本題へと進む前に発表当日に利用した資料も埋め込んでおきますので、併せて参照していただければと思います。

LINEの新卒採用について

採用のフローについてですが、エントリーしていただいた後にオンラインで実施しているコーディングテストを受けていただきます。Web上で出題がありますので出題の要求を満たすコードを制限時間以内に書いて提出していただきます。Web上にてある程度のテストケースを実行可能ですので、出題文をよく読みテストケースをパスする実装を行ってください。

コーディングテストの提出後に、弊社の選考担当による選考を行い、その後エンジニア面接、そして技術役員面接があります。
大まかな流れは以下の通りですが、それらのテスト/面接をすべて経たあとに内定となります。

なお、昨年と同様コーディングテストに限り何度不合格しても次のタームに再チャレンジできるRe-Challenge制度を設けています。
詳しくは技術職の採用フローについてで説明してありますので、ご確認ください。

今年ならではの特徴について

今年は昨年までと大きく変わった特徴があります。昨年まではコーディングテストとして、ある程度要件がシンプルなアルゴリズム問題を2問出させていただきましたが、今年はアルゴリズム問題を1問。そして業務志向な実装問題を1問の計2問を出題しています。

業務志向な実装問題とは?

唐突に「業務志向な実装問題」といわれてもよくわからないかと思います。いったいなんぞや?という話になってきますが、例えば8クイーン問題などよくあるアルゴリズム問題ですと、確かにロジカルな実装能力などを測ることはできます。しかし実際のLINEの開発の現場では企画者や様々な立場の担当がサービスの仕様を決めて、それらの仕様をいかにバグなく効率的に実装していくか?といった技能が重要になっていきます。

今回の業務志向な実装問題とは、そういった実際のサービスに近い仕様(とはいえ、かなりシンプルな要件になっています)をもとにして、その仕様から求められているアプリケーションを実装できるか? といった観点で判断するために、昨年までとは違う傾向の問題を追加させていただきました。

具体的な問題の傾向

実際に今回出題した過去問の傾向としては、私たちにとって身近なシステムをもとに出題しています。例えば今回解説する過去問ではタクシーメーターが題材となった問題になっています。

タクシーメーターも一見単純な足し算に見えますが、距離計や速度計、深夜時間などなど複数の要素があるので、2〜3時間くらいの制限時間で満点を取るにはなかなかの難易度設定になっています。

採点時にのみ実行する隠れたテストケースが存在しているのですが、受けていただくタームによってはエラー処理に関するテストケースが膨大なので、しっかりと仕様を読み解いて正しくエラー処理も実装していく必要があり、単純な計算処理だと思って油断していると点数が低い結果で終わる。といった悲劇も待ち受けています。

今回特にエラー処理の実装が出来ているかを重視して設題する傾向があります。重視する理由なんですが、やはり正しいサービスを開発していく上でエラー処理というものを適当に扱ってしまうと想定外のバグを多数混入してしまう原因になってしまうんですよね。

例えば、現金を取り扱うサービスなどで想像してもらうとわかりやすいとは思うのですが、タクシーメーターの計算がバグってて本来の倍も料金請求されるようなタクシーは嫌ですよね? 我々プロのエンジニアはそういった問題を起こすことなく実装していくことが当たり前のように求められています。
何事も仕様をしっかりと読むことが大事になっていきます。

対策方法

ここから、コーディングテスト受けるにあたっての対策方法を説明していきますが、これは単純で、本気を出すコンディションを作ってから挑むことが一番大事です。

今回のコーディングテストは全部で2問ありますが、全部を1日で解答する必要はないので1日に1問ずつ解くなどして十分に頭が使える状態で挑んでいただくことをお勧めします。
解答時間も2〜3時間くらいと長丁場で、本気でやろうとすると時間ギリギリまでかかることが多いようです。なので、ちゃんと長時間本気を出せるコンディションというものが大切になってきます。

環境整備

自分が本気を出せる最高の端末、最高のキーボード、最高のエディタ、その他必要な最高の環境を準備の上挑んでください。Web上でのコーディングテストとなっていますが、手元の端末でコードを書いていただくことはもちろん可能です。

コーディングテストのシステムに慣れる

エントリーしてしばらくしますとコーディングテスト実施のためのメールが送信されてきます。まずはじめにしていただきたいことは、Webテストのリンク先で案内しているチュートリアル問題を触ってください。

もしも実装を複数のファイルで行いたい場合などは、ディレクトリやファイルの作り方も覚えるようにしたほうが良いです。
特に、テストケースがどこにどのように格納されているかを調べると、ローカルで実装する時にローカルでテストケースを動かせるようになるので有利です。

コツ

仕様の文章は存外長めなので、最初に全体像を眺めつつどう実装していくかを決定していくと良いです。コーナーケースを突いてくるテストケースが多めなので、ある程度手元でテストコードを書きながら進めると手戻りは少ないかと思います。
初期で大事なのは、早い段階でテストケースをどれか1つ通るようなコードを書くことです。後半までテスト通さずに実装が大きくなってくると、テストが1つも通らない状況になってしまった場合のリカバリーが険しくなってきます。。。

最初に小さくテストを通すようにして、徐々に通せるテストを増やしていく方が気持ち的にも余裕を持って進められるかと思います。
過去の傾向としては単純な算数問題が多いのですが、要件の組み合わせパターンがいくつかあり仕様としては若干複雑になっていますので、手元で簡単に要件整理やエラーの条件一覧などのメモを取りながら進めていくと良いです。後半にバグを直す作業に入ってきた時は余裕がなくなり混乱しやすくなっているので、自分なりにわかりやすいまとめがあると安定して後半も乗り切れると思います。

LINEで働く上で大事な技能もみている

制限時間以内に満点が取れるコードが書ければ良いかというとそういうわけでもなくて、きちんと読みやすいコードになっているか?他人が理解しやすい設計で書かれているか?などといった可読性の面でも評価されます。

LINEではチーム開発というものを特に大事にしている会社です。チームメンバーが理解しやすいコードを書く技能や、多数のメンバーと協業しやすいコードを書く技能が重要となっています。
なので、他人(未来の自分も他人です)が読みやすいコードが書けるか否かも評価の軸として組み込まれています。
また、大量のトラフィックを捌くサービスを開発する上では、ある程度の計算量以内で実装する能力も大事ですので、隠れたテストケースの中計算量が多いコードはタイムアウトしてしまうテストケースも紛れていることがあります。

実際の問題の解き方

今回は、タクシー料金を計算するシステムを構築するという要件の設問を例題として、実際の問題内容の説明や、それを私ならどう解くか?といった解答するまでの考え方、実際にこの問題で私がハマったポイントなどの説明をしていきます。

問題内容

どういった問題が出るのかを見た方が早いので、実際の問題画面からのスクショを以下に引用します。

他のタームに比べると、この回の文章量は割と短い方です。

問題文サマリー

問題は大体以下のような要件を満たせ!といった内容になっています。

  • タクシーメーターを作れ!
    • 距離メーター,低速走行時間メーター,運賃メーターの3種類のメーターが搭載されている
  • 料金計算方法が複数あるよ
    • 初乗り運賃, 近距離運賃, 長距離運賃, 低速走行料金, 深夜料金, ピークタイム料金

ほとんど単純な算数だけど、料金計算が若干複雑そうですね?

入力データ

入力データもわりと単純で以下の形です。

  • 1行に現在時間と乗車距離が記録されている
    • 2行目以降は、一つ前の行から移動した距離が書かれていて、1行目からの累計の距離では無い
    • この距離を利用して、タクシーが時速何キロで走っているかを把握しておく事が重要
  • 現在時間は24時間制の時計ではなく、乗車中は99までカウントされる
    • 23時に乗車して3日間乗車し続けると95時間といった表記になる

現実だと95時間も走り続けることは出来ないんですが、あくまでもコーディングテストなので長時間運転することがある前提でテストケースが書かれてたりしています。

実際の入力データはテストケースの中で見ることができて、以下のような形です。

エラー定義

エラーも、この問題文の文量の割には細かく書かれていて以下のような定義です。

  • ‘時間 距離'(厳密にはhh:mm:ss.fff<SPACE>xx.f<LF>’)以外のフォーマット
    • hhは00-99の範囲
  • 空行はエラー
  • 上の行から時間順でソートされてないとエラー
  • 上の行から45秒を超えていたらエラー
  • 1行目は初乗りレコードであるが、距離が0.0以外の値になってる
  • 2行未満のデータしかない
  • 全体の走行距離が0.0メートルの時

ただし入力される行の行数は最大でも5万行以内であることを保証してるので、行数オーバの検出は不要になっています。

料金計算ルール

今回の問題の肝心な要件であるタクシー料金の求め方ですが、なかなかややこしくなってます。

  • 初乗り時に400円加算する
  • 累計距離が一定数超えるたびに特定の料金を加算する
  • 短距離(累計乗車距離1000m〜10200m)の時: 400mごとに40円加算
  • 長距離(累計乗車距離10200m以上)の時: 350mごとに40円加算
  • 10km/h以下の低速走行の累計時間が45秒を超えるごとに40円加算
  • なお料金加算時に以下の時間帯の場合は、加算額にそれぞれの料率を増した上で加算させる
    • 深夜時(AM0時〜AM6時)は30%増し
    • ピーク時間(AM6時〜AM9時30分 or PM18時〜AM0時)は50%増し

ちょっとぱっと見で整理仕切れないので、基本的な部分の料金計算を図に書くと以下のような感じです。

上の方でも書きましたが、手元で整理することの必要性がお分かりになったと思います。

俺ならこう解く!

実際に私もこの問題は満点が取れるまで何度もチャレンジしたことがあるのですが、満点が取れるころに悟った最適な実装の順番は以下のような形になるんじゃないかなと思いました。

  • 時刻をhh:mm:ss.fffからmsecに変換する
  • 距離を10かけて浮動少数処理を行わないようにする(理由はあとで)
  • msecを入力として、その時間が深夜帯かピーク帯かを判定するメソッドを実装
  • 加算したい料金とmsecを入力として、時間帯ごとの割増料金を考慮した料金メータ加算処理を書く
  • 初乗り運賃を加算する処理を書く
  • 走行距離を加算する処理を書いて、短距離/長距離の区切りごとに料金加算する処理を書く
  • 低速走行判定処理を書いて、低速走行時間を加算する処理を書き、45秒ごとに低速料金を加算する処理を書く

この解き方が最適かと言われると言葉に詰まってしまいますが、、最初の方は各種計算が楽になるような設計で基本的な部分の実装していき、徐々に本題となるメータを実装して点数を取れるようにし、応用的な要件の実装を埋めて満点を目指す。といった進め方をしました。

ハマったところ

最後にこの問題を解くにあたってハマった部分なのですが。。。

  • 仕様を読み飛ばしたせいでコーナーケースのテストが通らない
  • 純粋に足し算したので距離がずれてしまった。。
    • 浮動小数点の演算考慮不足
  • デバッグ処理入れたり戻したりしてるうちに実装バグる。。。
    • テストコードちゃんと書くの大事。。
  • 単純に計算するとデータ量が多くてタイムアウトになってしまう

心の傷が増えてしまうのでコメントは差し控えさせていただきます。。。

終わりに

今回の例ではタクシーメータを実装するという内容なのですが、別タームではまた違った要件になっていて求められる設計力も変わります。

私自身も時間が許す限り、全部の問題が100点満点取れるまでコードを書き続けたりしている(とある1タームだけ時間の都合で断念)のですが、実務経験者目線でも設問の複雑性により解くのが面倒に感じてしまうものから、なにも考えなくてもうっかり解いてしまう要件まで、多様性のある問題が毎回出題されています。

資料公開後にネット上にて「俺には無理そう」「難しい」などの感想の声もちらほらと見かけましたが、本記事でも伝えた通り現実世界の要件をコードにうまく落とし込むトレーニングを続けていけば案外あっさりと合格ラインに乗るかもしれません。

最後ありきたりな言葉になってしまいますが、皆さんと一緒に働ける日を楽しみにしております!LINEのサービス開発に興味がありましたら是非是非この記事を参考にして応募してください!