こんにちは、Habr!
7月に、PHP開発者向けの募集イベントを開催しました。その結果、5人がロンドンオフィスへのオファーを受け取りました。 私たちは急速に成長し続けています。AndroidとiOSのチームは11人で成長しているため、PHP開発者向けのコンテストを再び開催しています。
ルールは同じです。 テストで高い結果を示し、モスクワで2月10日または11日に面接に合格しました-Badoo Londonオフィスに申し出ます。
同社は、モスクワへの面接に到着するためのすべての費用と、ロンドンへのさらなる移動に関連するすべての費用を負担します:家族の労働ビザ、移動、英語の向上、住む場所の発見のための10,000ポンド(約770,000ルーブル)。
テストタスクを完了するために、カットの下の多数の要求( 1、2、3 )に従って、以前のイベントからのタスクを分析し、それらの正しい解決策を検討し、それらを選択した理由を説明し、いくつかの例、統計、オプションも示します候補者からの決定。
UPD:イベントが完了しました。 その結果、7人が参加しました。
まず、オンラインテストは妥協であることに注意してください。 これは、人間の知識とスキルの総合的な評価であり、実際の問題を解決する能力と相関していますが、必ずしも正確に反映しているわけではありません。
Badooの私たちは、人、個人の資質に依存しています。 したがって、私たちは常に可能な限りインタビューをパーソナライズしようとします。私たちにとっては、問題を解決するという事実ではなく、人がどのように考え、推論するかが重要です。
したがって、テストで幸運でない場合、落胆しないでください。 標準的な方法で私たちに従ってください-そしておそらくあなたは私たちの定期的なインタビューでより良いことが証明されるでしょう。 ロンドンに移りたくない人にも同じことが言えます。モスクワには空室があります!
それでも、最初の選択は何らかの形で必要であるため、このためにオンラインテストを使用することにしました。
テストのタスクの選択を正当化するには、まず、一般的にそれを使用する理由、テストの内容と方法を説明する必要があります。
そのため、このテストでは2つの問題を解決できます。
- 基本的な要件を満たす候補者を選択するのは簡単です。
- 要件に適したものの中から、最適なものを選択します。
一次選択
自動検証を使用してSQLおよびPHPコードを記述するタスクの助けを借りて、プライマリ選択の問題を解決します。 自動化のおかげで、前回受け取った950のソリューションのうち150のみがチェックされました。 それは約15%です。
ベースとして、次の要件を設定しました。
- PHPの知識(「平均」レベル)。
- SQLの知識(「平均」レベル)。
- コンピュータサイエンスの一般的な理解。
- 英語の最低限の知識;
- 問題を解決するためにこれらのスキルを適用する能力。
最高
選考の第一段階を通過した候補者は、すでに非常に優れています。 これは彼らの完全な準備を意味するものではありませんが、適切な基盤は、人がすでに私たちに適切であるか、適切なトレーニングで将来的に適切であるという保証です。
潜在的に適切なものの中から最良のものを選択する方法は? このプロセスを形式化するのはより困難です。 そのため、この段階で、さまざまな分野の知識と経験を実証するために、広範囲のタスクを使用することにしました。 そして、そのような能力のそれぞれの成功した使用はプラスと見なされました。
すべての領域を1つのリストでカバーすることは不可能なので、注意を払ったトピックの例をいくつか示します。
- Linuxコンソール
- LNMPスタックのさまざまな部分のデバッグ。
- ネットワークビュー、HTTP(S)、TCP / IP;
- キュー、メッセージブローカー、並列処理。
- 最適化(My)SQL;
- データの整合性の確保(トランザクション、分離);
- 高負荷固有のもの(スケーリング、シャーディング、キャッシング);
- OSのCPU、メモリ、タスクスケジューラの一般的な考え方。
- 設計、システムアーキテクチャ。
- ...
タスク
その結果、要件を満たす6つのタスクを選択しました。
- 3つはコードの作成を自動的にチェックします。2つはPHPに、1つはSQLにあります。
- 無料の推論のための3。
すべてのタスクテキストは英語で書かれているため、それらの最低限の知識は自動的にチェックされました。
ここでは、便宜上、ロシア語のテキストを引用し、エッセンスのみを残して可能な限り減らします。
たとえば、前のテストの3つのタスクを分析します。
タスク番号1。 「多数の合計」
状態
スペースで区切られた2つの正の整数を含む文字列を指定します。 数値は大きい場合があり、64ビット整数に収まらない場合があります。 これらの数値の合計を印刷する必要があります。
典型的な解決策
function sum_str($str) { list($s1, $s2) = explode(' ', $str); $l1 = strlen($s1); $l2 = strlen($s2); $result = ""; $rest = 0; for($i = 1; $i <= max($l1, $l2) + 1; $i++) { $d1 = $s1[$l1 - $i] ?? 0; $d2 = $s2[$l2 - $i] ?? 0; $sum = $d1 + $d2 + $rest; $rest = intval($sum > 9); $result .= $sum % 10; } return strrev(rtrim($result, '0')); }
タスクは簡単です。 それを使用して、PHPでプログラムする機能をテストします。 201人が完全に正しく決定しました。 さらに63人の候補者がテストシナリオの一部を受けましたが、一部の境界ケースは合格しませんでした。
ソリューションの可能な最適化の1つは、サイクルの各反復で、1ビットの数ではなく、一度に複数(N)を取ることです。 PHPではすべてのintが署名されるため、N桁で構成される数値とそのような2つの数値の合計の両方が63ビットに収まることを考慮することが重要です。 一度に最大18ビットを使用できることがわかりました。
そのような決定を興味深いものとしてマークしましたが、それらに頼ったのはごくわずかでした。
タスクの公開後、プラットフォームでは利用可能なPHP拡張を管理して解決できないことがわかりました。 したがって、GMP(gmp_add())およびBC Math(bcadd())を使用して問題を解決することもできます。 この場合、それらは数行のコードに落ちたという事実にもかかわらず、私たちはそのような決定を他の人と同等に真実とみなしました。
タスク番号2。 「ブラケット」
状態
入力には、セット{}()[]からの括弧のみを含む行があります。 バランスが取れているかどうかを判断する必要があります。
バランスとは、次の3つの条件が満たされる文字列を意味します。
- 各開始ブラケットには、 対応する終了があります。
- 対応する閉じ括弧は、開きの後でなければなりません。
- 2つの対応するブラケットの間に、これらのブラケットの間に対応関係がない他のブラケットはありません。
つまり、[([] {[]})]はバランスが取れていますが、{[}}、[{)]および] {}はバランスが取れていません。
典型的な解決策
function balanced($str) { $braces = [ '}' => '{', ')' => '(', ']' => '[', ]; $stack = []; for($i = 0; $i < strlen($str); $i++) { $char = $str[$i]; if (isset($braces[$char])) { $el = array_pop($stack); if ($el != $braces[$char]) { return 'NO'; } } else { array_push($stack, $char); } } return $stack ? "NO" : "YES"; }
このタスクでは、PHPの一般知識とコンピューターサイエンス(アルゴリズム)の両方をテストします。 完全に正しく、231人が決定しました。 別の99人の候補者がいくつかのテストシナリオに合格しましたが、すべてではありませんでした。
この問題を解決する最短の方法は、ストリングの変更が停止するまで、ループ内のストリングからすべての「()」、「{}」、および「[]」の組み合わせを削除することです。 この決定を下しましたが、最適ではないとマークしました。 この場合、スタックの決定は1つのパスで実行され、O(N)の複雑さを伴いながら、ラインとメモリの割り当てに沿って多くのパスを作成する必要があります。
一部の参加者は、array()の代わりにSplStackを使用してスタックを実装しました。 ただし、SplStackはユニットを使用していましたが、このようなソリューションは同等と考えました。
タスク番号3。 ウィキペディア
状態
英語版ウィキペディア(HTMLのみ、写真、CSS、JSなし)のすべてのページをダウンロードするタスクがあります。
10個のサーバー(それぞれ24コア)、無限の高速ディスクとRAM、およびギガビットインターネットがあります。
タスクを完了するために必要な時間を評価し、ソリューションアルゴリズムを記述することで正当化する必要があります。 コードは不要です。
説明
このタスクの助けを借りて、候補者が実際のタスクを「人生から」分解し、重要な情報を状態から分離し、時間枠を正しく決定/正当化する能力を評価したいと考えました。
ここには参照ソリューションはありませんので、最初に注意した主なポイントを紹介します。
- ウィキペディアのページ数(現在5,548,604)を決定し、 そのページのインデックスを見つけます 。
- ネットワーク帯域幅の観点からコンテンツを転送するのにかかる時間を計算します。 平均ページサイズを30 Kbとすると、Wikipedia全体が5548604 * 30 Kb≈166 GBを占有します。 ネットワークを介した送信には、(5548604 * 30000 * 8)ビット/ 10 ^ 9ビット/ s≈1331 sかかります。 ≈22分。
- ネットワークの応答時間を見積もります。 平均応答時間に50ミリ秒かかる場合、すべての遅延の合計は5548604 * 0.05 = 277430.2 sに等しくなります。 ≈3.2日;
- 各サーバー内およびサーバー間でタスクを並列化することを提案します。 作業上の決定はすべて行われました。キューサーバー、データベースのどこかで開始し、何らかの形でタスクを部分に分割します。
- 並列ハンドラーの数(N)の選択を正当化します。 プロセッサ時間はネットワーク上の応答時間よりもはるかに短いため、Nはコア数(> 10 * 24)よりも多く取ることができます。 また、ここでは、実行の1つのスレッド(イベントループ、curl_multi_execなど)のフレームワーク内で「非同期コード」を使用する可能性に言及できます。
- たとえば、N = 1000の場合、5548604 * 0.05 / 1000 = 277秒になります。 約4.6分。これは、実装の時間と比較して既に非常に短いです。
- 開発、デバッグ、および実行に時間を追加します。 私たちは主に正当化に注意を払った決定を研究しながら、多かれ少なかれ正当化された期間を取りました。 非常に長い期間(週以上)を提供する候補者がいましたが、今回は何が必要かについての説明はありませんでした。 そのような決定はあまりうまくいかないと考えました。
多かれ少なかれ、12人がこのタスクに対処しました。 別の55人が部分的に解決しました。
新しいテストを受ける場所。
タスクの選択方法とソリューションの評価方法が明らかになったので、イベント、条件、および新しいテストの詳細な説明がここにあることを思い出してください。 あなたは1月26日までそれを通過することができます。
Habré での前回のイベントの発表から、チームとタスクについて詳しく知ることができます。 そしてここで、同僚のアントン・ルサコフのロンドンへの移住に関するサクセスストーリーを読むことができます。
質問がありますか? コメントで彼らに尋ねるか、Habropostに私を送ってください。
テストを受け、面接に来てください-そしてフレンドリーなチームに参加しましょう! 面白いでしょう!
頑張って!
Badoo、PHPチームリーダー、Pavel Murzakov氏。
UPD: 2月7〜8日まで回答します。
UPD2:イベントが完了しました。 その結果、7人が参加しました。