8つのボール問題、書き直し(JavaScript手習い)
先ほどの解答(http://d.hatena.ne.jp/torazuka/20130626/balls)を書き直します。
- 配列Xを配列a, b, cに分割するイディオムを知りたい
単なるArray.sliceでいいのでは、と気づいて書いてみましたが、エラーになってしまいました。 slice(start, end+1)すべきところで、slice(start, num)していたせいでした。(hirataraさんありがとうございます)
exports.solve = function(balls){ var right = balls.slice(0, 2); // エラー
仮引数に入ってくる値がArrayかどうか分からない状態ではsliceできない、ということでしょうか。分かりません。
とりあえず、今回は要素が8個固定なので、添え字を元に分割することにしました。
- 配列a, b, cで、元の配列Xの添え字を保持したい
構造体みたいなのを作りました。thisやnewを使うなとあれほどいわれているのに使ってしまった。
書き直した解答
var _ = require("./lib/underscore-min.js"); exports.ball = function(i, w){ this.index = i; this.weight = w; return this; }; exports.solve = function(balls){ // 3, 3, 2ずつ取り出して比べる var right = balls.slice(0, 3); var left = balls.slice(3, 6); var other = balls.slice(6, 8); var rsum = _.reduce(right, function(memo, num){ return memo + num.weight; }, 0); var lsum = _.reduce(left, function(memo, num){ return memo + num.weight; }, 0); if(lsum === rsum){ // 3, 3が釣り合ったら残り2つで比べる return other[0].weight < other[1].weight ? other[1].index : other[0].index; } // 右(左)の方が重ければ右(左)から1つずつ取り出して比べる if(lsum < rsum){ return comp(right); } else { return comp(left); } function comp(targets){ if(targets[0].weight === targets[1].weight){ return targets[2].index; } return targets[0].weight < targets[1].weight ? targets[1].index : targets[0].index; }; };
テストコード。
var assert = require('assert'); var gb = require("./googleBall.js"); describe('8つのボールから1つだけ重いボールのインデックスを返す', function(){ it('重いボールが先頭にある場合', function(){ var ball = gb.ball; var answer = gb.solve([new ball(0, 7), new ball(1, 5), new ball(2, 5), new ball(3, 5), new ball(4, 5), new ball(5, 5), new ball(6, 5), new ball(7, 5)]); assert(answer === 0); }) it('重いボールが中央付近にある場合', function(){ var ball = gb.ball; var answer = gb.solve([new ball(0, 5), new ball(1, 5), new ball(2, 5), new ball(3, 5), new ball(4, 7), new ball(5, 5), new ball(6, 5), new ball(7, 5)]); assert(answer === 4); }) it('重いボールが末尾にある場合', function(){ var ball = gb.ball; var answer = gb.solve([new ball(0, 5), new ball(1, 5), new ball(2, 5), new ball(3, 5), new ball(4, 5), new ball(5, 5), new ball(6, 5), new ball(7, 7)]); assert(answer === 7); }) });