ドワンゴ 技術コミュニケーション室の塩谷( @kwappa / @kwappa@friends.nico )です。
9/16に開催された「学びの秋!エンジニア最先端に触れて学ぶITフェス」というイベントにドワンゴも企業として出展し、私も職務経歴書についての講演を行ってきました。ご清聴いただいた皆様、ありがとうございました!
さて、企業ブースでは「ドワンゴからの挑戦状」と題したプログラミング課題を用意し、正解者には先着順でアスキードワンゴの技術書をプレゼントする企画を実施しました。「ヒントが欲しい」「解き方を教えてください」という要望も多かったので、解法をJavaScriptによるサンプルコードを添えて紹介します。
解答と解説
Q1 : 101
力技で解くなら、2525から1までのループを回し、その数と2525および5252の剰余を求め、いずれも0になる最初の数、ということになります。
let a0 for (let i = 2525 ; i > 0 ; i --) { if (2525 % i === 0 && 5252 % i === 0) { a0 = i break } }
最大公約数を求める有名な方法に「ユークリッドの互除法」があり、そちらを使えばより計算量少なく求めることができます。
x <= y , x > 0 , y > 0 の場合、以下のコードで最大公約数が求められます。互いに素な場合は1が返ります。
function gcd(x, y) {let rwhile (y > 0) {r = x % yx = yy = r}return x}const a1 = gcd(2525, 5252)
Q2 : 2859870693
漸化式なので、設問通りの演算をする関数を再帰的に呼び出せばn項めを求めることができます。ですが、Q3とQ4が同様の数列を利用する問題になっているため、ここで全要素を演算した配列を生成した方が楽でしょう。
2 ^ 32 はこのあとも使うので、ここで定義してしまいましょう。ES2016からは 「2 ** 32」 と書くこともできます。
const TWO_POW_32 = Math.pow(2, 32)let arr = [a1]for (let i = 1 ; i <= 1000 ; i ++) {arr[i] = (arr[i - 1] * 2525 + 5252) % TWO_POW_32}const a2 = arr[1000]
Q3 : [2355222565, 3890716245, 434637493, 1285940997, 3265016661, 5746901]
文字コードをindexとして先ほどの配列から取り出し答えとなる配列にpushしていく、という戦略が考えられます。
文字列を配列に分解するにはスプレッド演算子が使えます。 以前は `'dwango'.split('')` という書き方をすることが多かったようです。
const a3 = [...'dwango'].map(v => arr[v.charCodeAt(0)])
Q4 : 2110379477
ソートして取り出すだけの問題です。500番目はちょうど真ん中なので、昇順 / 降順を間違えても解答は変わらないというボーナス問題です。
JavaScriptの場合は単純に `Array#sort` でソートすると文字列として辞書順でソートされてしまうので、比較関数を書いて数値でソートする必要があります。
const sortedArr = arr.sort((a, b) => a - b)const a4 = sortedArr[500]
問題 : 3322
JavaScriptではreduceというメソッドで畳み込み演算を行うことができます。Q3で作った配列に残りの値を連結した配列を作り、すべての値を合計し、2 ^ 32との剰余を求め、先頭4文字を取り出してみましょう。
const answerArr = a3.concat([a1, a2, a4])const answer = ((answerArr.reduce((a, x) => a + x))% TWO_POW_32).toString().slice(0, 4)
蛇足
筆者の趣味でRubyによる解答例も掲載しておきます。 Integer#gcd とか Array#sum (2.4から)など便利メソッドがあることをコードレビューで教えてもらいました。
a1 = 2525.gcd(5252)puts "Q1 : #{a1}"
arr = [a1]1.upto(1000) { |idx| arr[idx] = (arr[idx - 1] * 2525 + 5252) % 2 ** 32 }a2 = arr[1000]puts "Q2 : #{a2}"
a3 = "dwango".each_byte.map { |idx| arr[idx] }puts "Q3 : #{a3}"a4 = arr.sort[500]puts "Q4 : #{a4}"
answer = (a3.concat([a1, a2, a4]).sum % 2 ** 32).to_s[0..3]puts "Answer : #{answer}"
まとめ
当日会場では「5分で解けた」から「難しすぎてギブアップ」まで、さまざまな感想をいただきました。みなさまはいかがだったでしょうか。
ドワンゴではエンジニアを積極的に採用しています。「解けた!」という方で、お仕事をお探しの方は、経験者採用の募集情報もぜひご覧ください!
ドワンゴではエンジニアを積極的に採用しています。「解けた!」という方で、お仕事をお探しの方は、経験者採用の募集情報もぜひご覧ください!
コメント
コメントを書く