hakobera's blog

技術メモ。たまに雑談

JavaScript で for/while 文を使わないで1から10までの合計を求める方法

Node.js 初心者に非同期(ネットワーク)、コールバック、ECMAScript5 について理解してもらうのにいいネタはないか考えてみた。

その結果、「for 文を使わないで1から10までの合計を求める」プログラムを書いてもらうのはいいんじゃないか、と思ったので、思いついた分だけ以下に書いておきます。

いずれも Node.js v0.6.2 の REPL で動作確認しています。
配列を破壊しているものとかもありますが、その辺は制約条件にしていないので、ツッコミはなしでお願いします。

Array#forEach を使う

var sum = 0;
[1,2,3,4,5,6,7,8,9,10].forEach(function(element, index, array) {
  sum += element;
});
console.log(sum);

Array#reduce を使う

var sum =[1,2,3,4,5,6,7,8,9,10].reduce(function(previousValue, currentValue, index, array) {
  return previousValue + currentValue;
});
console.log(sum);

reduce の代わりに、 Array#reduceRight を使っても結果は同じ。

var sum =[1,2,3,4,5,6,7,8,9,10].reduceRight(function(previousValue, currentValue, index, array) {
  return previousValue + currentValue;
});
console.log(sum);

setTimeout を使う

var ary = [1,2,3,4,5,6,7,8,9,10],
      sum = 0;

var sumFunc = function() {
  sum += ary.pop(); // shift や splice を使っても良い
  if (ary.length > 0) {
    setTimeout(sumFunc, 0);
  }
};
sumFunc();

console.log(sum);

Google Suggest API を使う

var http = require('http'),
    querystring = require('querystring');

var options = {
  host: 'www.google.co.jp',
  port: 80,
  path: '/complete/search?output=toolbar&q=' + querystring.escape('1+2+3+4+5+6+7+8+9+10=')
};

http.get(options, function(res) {
  res.setEncoding('utf8');
  res.on('data', function (chunk) {
    var sum = chunk.match(/calculator_suggestion data="(\d+)"/)[1];
    console.log(sum);
  });
});                                                                           

以下、追記

Sleep Sum ?

@shibukawa さんから「setTimeoutに数値で時間を渡して(1000倍して)、経過時間を測るのは?」という意見があったので書いてみました。

var sum = 0;                                                                        
var base = Date.now();

function addTime() {
  sum += (Date.now() - base) / 1000 | 0;
}

// for が使えないので自力で 
setTimeout(addTime,  1  * 1000);
setTimeout(addTime,  2  * 1000);
setTimeout(addTime,  3  * 1000);
setTimeout(addTime,  4  * 1000);
setTimeout(addTime,  5  * 1000);
setTimeout(addTime,  6  * 1000);
setTimeout(addTime,  7  * 1000);
setTimeout(addTime,  8  * 1000);
setTimeout(addTime,  9  * 1000);
setTimeout(addTime, 10  * 1000);
 
setTimeout(function() { console.log(sum);  } , 11 * 1000);

process.nextTick を使う

こちらは @jovi0608 さんから教えてもらった方法です。process.nextTick を利用した Node.js ならではのコードですね。

JavaScript で for/while 文を使わないで1から10までの合計を求める方法(node-fibの真似編) — Gist

var calc = function(n, callback) {
  var sum = function(i, res) {
    var func = (n>i) ? sum_tick : function(j,k) {callback(k);};
    func(i+1, res+i);
  };
  var sum_tick = function(i, res) {
    process.nextTick(function() { sum(i,res); });
  };
  sum(1,0);
};
calc(10, function(x) {console.log(x);});

ちなみに process.nextTick 使わなくても書けます。計算量が多い場合は、上記のコードの方が速くなるようですが、計算量が少ない場合は以下の方が速いようです。なかなか奥が深いですね。

JavaScript で for/while 文を使わないで1から10までの合計を求める方法(process.netxtTick()を使わないnode-fibの真似編:実はこっちの方が速かった) — Gist

var calc = function(n, callback) {
  var sum = function(i, res) {
    var func = (n>i) ? sum : function(j,k) {callback(k);};
    func(i+1, res+i);
  };
  sum(1,0);
};
calc(10, function(x) {console.log(x);});