はじめに
いつもは「マンガで分かるプログラミング用語辞典」でマンガを描いている柳井です。今回は「CodeIQ」という「ITエンジニアのための実務スキル評価サービス」で、プログラミングの問題を出しましたので、その結果報告をしようと思います。
まずは、問題に解答いただいた方に、お礼と感謝の意を表しておきます。
解答者と出題者の双方にメリットがある「CodeIQ」
それでは、「CodeIQ」がどういったサイトなのかを紹介します。このサイトには、常時20~30問ほどの、「ITエンジニア向けの問題」が掲載されています。プログラミングでは、Ruby、PHP、Java、JavaScript、SQL、言語問わずといった、各種言語の問題が出ています。またプログラミングだけでなく、レポート作成や、データ分析など、多彩な問題が掲載されています。そしてこの問題に解答すると、出題者から直接フィードバックが得られます。
同様の出題サイトはよくありますが、通常は解答が発表されるだけです。しかし「CodeIQ」では個別に返信がもらえます。それも出題者からです。そしてその出題者達は、いずれもその分野で実務を行っている人達です。現場の人のリアルな声で、自分のスキルを評価してもらうことができるわけです。
また出題者側にとっては、実務をそのまま任せられるエンジニアを探す手段にもなります。通常の人材募集では、人事を通して人を募集して、面接などでスキルを推測します。しかし、現場の実務に即した問題を出題し、その解答を受け取ることで、その業務をこなせる人を一本釣りすることができます。これは解答者側にも就職のチャンスになります。
このように「CodeIQ」は、解答者と出題者の双方にメリットのあるサービスになっています。以下、それぞれのメリットをまとめます。
解答者側のメリット
- 実際の現場のデータや、そこで起きるケースに即した問題が出題される。
- 出題者から直接フィードバックを得ることができる。
- 場合によっては、出題者から「うちの会社に来ない?」と声を掛けられる。
出題者側のメリット
- 自社の業務に即戦力となる実力を持っている人を探せる。
- 通常の求人とは違い、技術者が直接人材を見極めることができる。
- プログラミングや、レポート作成、データ分析など、多様な問題を出題できる。
では、この「CodeIQ」に、私が実際に出題した体験報告をしようと思います。以下、簡単な目次です。
- 出題の経緯:出題の経緯、出題意図、問題の設計
- 出題の結果:成績の分布、評価の判断
- 解答例:解答例をいくつか掲載
記事執筆時点(2012年12月)までに、以下の3種類のコードゴルフ問題を出しています。今回は1件目の話になります。3件目は、記事掲載時点ではまだ受付中ですので、是非ご参加ください。
- 【1件目】コードゴルフ:最短コードを書く!(受付期間:2012年11月10日~12月10日)
- 【2件目】サンタのためのコードゴルフ(受付期間:2012年12月6日~12月25日)
- 【3件目】コードゴルフ:迷路(受付期間:2012年12月27日~2013年1月24日)
主な利用対象者
- 解答者側: ITエンジニア系の面白い問題を解きたい方。自分の実力を測りたいITエンジニア。自分のスキルを評価して声をかけてくれる企業・人を探したい人。
- 出題者側: 企業のITエンジニア部門で、採用の権限を持っている人。あるいは、今後そういった可能性があると考えている方。
出題の背景
出題の切っ掛けは、「CodeIQ」の担当の方から「マンガ付きのプログラム問題」の出題を依頼されたことです。サイトへの集客と活性化が主眼ということでしたので、依頼通りの企画(マンガ付き問題)とは別に、依頼者側の本来の意図を満たすであろう企画を携えて打ち合わせに行きました。
工夫その1:明確な指標で競い合わせる
その企画が「ランキング付きのコードゴルフ問題」でした。私を含めてITエンジニアの多くは、「明確な数値で評価でき」かつ「自分の実力が絶対的評価で判定される」「パズル的な問題」に、かなり心を動かされます。そこで「コードゴルフ」を行うのが目的に適っているだろうと考えました。
「コードゴルフ」は、ゴルフがカップインまでの打数を競うように、プログラムのソースの文字を削り、なるべく短くプログラムを書く遊びです。以下、実例です。1から100までの整数をすべて足すプログラムです。
// 1から100の整数をすべて足す(77文字) var res = 0; for (var i = 1; i <= 100; i ++) { res += i; } console.log(res);
// 1から100の整数をすべて足す(38文字) for(r=i=0;i<=99;r+=++i);console.log(r)
// 出力 5050
また、すぐに結果が出て、確認できる方がよいだろうということで、出題のWebページには「プレイグラウンド」(実際にブラウザ上でコードを動かせる場所)も付けることにしました。そして掲載期間中は、ランキングを「CodeIQ」の公式ブログで発表していくことにしました。
工夫その2:スキルを判別する3つの仕掛け
さて、私の会社では、当面採用の予定がありません。とはいえ出題にあたって、「CodeIQ」の本来の意図である「ITエンジニアのための実務スキル評価」という部分は満たす必要があります。そこで問題の中に、解答者をふるい分けするための仕掛けを用意しました。ポイントは以下の3点です。
- 言語仕様の熟知
- 実務の発想
- アルゴリズム力
それでは実際の問題を掲載して、上記3つについて解説します。自分の実力に興味がある方は、解説を見る前に、5分から10分ほどの時間を掛けて、何文字まで縮められるかチャレンジしてみてください。解答の文字数は、「function yourCode() {★}」の「★」の部分の文字数になります。
function yourCode() { var res = ""; var w = 80; var h = 40; var sz = 30; for (var y = 0; y < h; y ++) { for (var x = 0; x < w; x ++) { var dstnc = Math.sqrt( Math.pow(w / 2 - x, 2) + Math.pow((h / 2 - y) * 2, 2) ); if (dstnc < sz) { res += "*"; } else { res += "-"; } } res += "\n" } return res; }
言語仕様の熟知
まずは知識の確認です。JavaScriptの言語仕様から、どうすれば文字数が削れるかという部分です。ここが覚束ないようだと、知識不足ということになります。一見して、どういったところが削れるかを示します。問題自体にも、少しヒントが入っています。
- タブ文字、スペース文字は削れる。
- コードゴルフということで「var」は削っても文句を言われない。
- JavaScriptでは、行末の「;」を削っても大丈夫。
- 「if」は「条件演算子(?:)」に置き換えられる。
- 「if」や「for」の「{ }」は削れる。
上記がすぐにできない場合は「あまりコードを書くことに慣れていないのかもしれない」という判定になります。これが、1つ目の判定ポイントでした。
実務の発想
問題にはトラップを用意しています。それは「Math.sqrt」「Math.pow」といった数学オブジェクトを使った計算部分です。
私は、iアプリ向けのゲームを作っていたこともあり、低スペックのマシンで、いかにゲームを動かすかということを行っていました。こういった環境では、「マシン環境に合わせた柔軟なソースを書く」ことが要求されます。実務では、こういった「環境に合わせたコーディング」が必要になることがあります。
そして低スペック環境では、呼び出しコストの高いオブジェクトへのアクセスがある場合は、「他の処理に置き換えられるのではないか?」と注目します。実際に、出題したコードでは、この部分を置き換えると文字数が激減するように設計しています。そこに気付いて、すぐに書き換えられるかどうかを1つのハードルにしました。
この仕掛けは有効に働き、「Math」をソースコードから削れた解答者は、だいたい100文字以下までソースを短縮できていました。また、「Math」を削れなかった解答者は、100文字を超える人がほとんどでした。
アルゴリズム力
「Math」の削除をクリアした後は、「計算手順を工夫する能力」の判定になります。同じ計算でも、コーディング次第で文字数を削ることができます。ここは「上級者の高度な戦い」になります。
このレベルで勝負をしている人は、基本的な能力は十分にある人だと思います。計算方法を工夫することで文字数を削ることができるレベルの人は、80文字台から70文字台で争っていました。最短でコードを書いた1位の人達(10人いました)は、75文字まで処理を短縮できていました。元が323文字なので、23%まで短縮できたことになります。
出題の結果
最終的な解答者の数は172人でした。その文字数の分布を掲載します。
最短の文字数の解答者は75文字でした。平均値は102文字です。100文字ぐらいで、上位と下位を分けられるだろうと思っていた当初の予想通りの数値になりました。
最大のボリュームゾーンは81~85文字になっていますが、これはランキングを細かく発表していたために、複数回投稿する人が多かったからです。自分の順位が分かると、さらに文字数を削ろうと考えるものです。もし比較する相手がいなければ、95前後が一番多かったのではないかと思います。
さて、コードゴルフの能力が、必ずしもその人のコーディング力を表しているわけではありません。しかし、ある程度の目安になると思われます。プログラミング言語の仕様をあまり把握していない場合は、「その言語に、あまり習熟していない」ことが推測できます。その反対に、言語の仕様はあっさりとクリアして、アルゴリズムの工夫に集中して、文字数を極限まで詰めて来た人は、柔軟な発想ができて、必要な環境に合わせたコードを書けることが予想できます。
そういった考えを元にして、実際に投稿していただいた172人の解答380件分にフィードバックを行い、私は解答を以下に分類しました。
分類 | 文字数 | 内容 |
非常に高度 | 90文字以下 | 言語の仕様を熟知し、要求された環境に最適なコードを、計算手順まで最適化して作成できる。 |
高度 | 91~100文字 | 言語の使用に習熟し、要求された条件を満たすコードを、計算手順を工夫しながら作成できる。 |
通常 | 101~120文字 | 特殊な環境を要求されない、通常の場面でのプログラミング能力があり、十分に業務を行える。 |
不慣れ | 121文字以上 | 指定のプログラミング言語あるいは、プログラミング自体に不慣れで、要求された業務を行うには不十分な可能性がある。 |
解答例
興味のある人が多いと思いますので、各文字数の典型的なコードを掲載します。最後の一つ以外は、サンプルとして、私が順に文字を削って作成したものです。
var r="",w=80,h=40,s=30; for(var y=0;y<h;y++){ for(var x=0;x<w;x++){ var d=Math.sqrt(Math.pow(w/2-x,2)+Math.pow((h/2-y)*2,2)); if(d<s){r+="*";}else{r+="-";} } r+="\n" } return r
r=""; for(y=0;y<40;y++){ for(x=0;x<80;x++){ d=Math.sqrt(Math.pow(40-x,2)+Math.pow((20-y)*2,2)); if(d<30){r+="*";}else{r+="-";} } r+="\n" } return r
r=""; for(y=0;y<40;y++){ for(x=0;x<80;x++){ r+=Math.sqrt(Math.pow(40-x,2)+Math.pow((20-y)*2,2))<30?"*":"-"; } r+="\n" } return r
r="",m=Math; for(y=0;y<40;y++){ for(x=0;x<80;x++){ r+=m.sqrt(m.pow(40-x,2)+m.pow((20-y)*2,2))<30?"*":"-"; } r+="\n" } return r
r=""; for(y=0;y<40;y++){ for(x=0;x<80;x++){ r+=Math.pow(40-x,2)+Math.pow((20-y)*2,2)<900?"*":"-"; } r+="\n" } return r
r="" for(y=0;y<40;y++){for(x=0;x<80;x++){a=40-x;b=(20-y)*2;r+=a*a+b*b<900?"*":"-"}r+="\n"} return r
r="" for(y=-20;y<20;y++){for(x=-40;x<40;x++){r+=x*x+y*y*4<900?"*":"-"}r+="\n"} return r
r="" for(y=-21;++y<20;r+="\n")for(x=-41;++x<40;)r+=x*x+y*y*4<900?"*":"-" return r
for(s='',x=y=n=40;y+n;s+='-*\n'[x+n?x*x--+y*y<900|0:(x=n,y-=2,2)]);return s
81文字までが普通の手法での文字の削減になります。それ以上は、大きな発想の転換が必要になります。そのため、解答者の点数分布グラフでも、数度にわたって投稿した人達の多くが81文字辺りで行き詰っていました。
80文字以下のコードでは、「文字列に添え字を付けることで、その位置の文字を取得できる」仕様を利用していました。1位の例として掲載させていただいた「tompng」様のコードは、募集期間終了後に、githubに解答が上げられていましたので、転載させていただきました。
まとめ
というわけで「CodeIQ」という、「ITエンジニアのための実務スキル評価サービス」を利用して、問題を出し、そのフィードバックを行いました。そして1か月にわたり、いろいろな方のコードに触れました。いつもとは違う、刺激的かつ有意義な時間を送ることができました。
自分の能力を試してみたい方も、求めているITエンジニアを探し出したい会社や技術者も、「CodeIQ」を利用してみると面白いと思います。
特に解答者の方は、最前線で活躍しているエンジニアの方々からのフィードバックを受けられるので、楽しいだけでなく勉強になると思います。答える側の私も、たいへん勉強になりました。
みなさん興味があれば、この「CodeIQ」の問題にぜひ挑戦してください。
参考資料
- CodeIQ ITエンジニアのための実務スキル評価サービス
- blog.code.iq│CodeIQ
- コードゴルフ:最短コードを書く!(受付期間:2012年11月10日~12月10日)
- サンタのためのコードゴルフ(受付期間:2012年12月6日~12月25日)
- コードゴルフ:迷路(受付期間:2012年12月27日~2013年1月24日)
- クロノス・クラウン