Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Codewars 練習 06:用函式計算

問題

給定 14 個函式,從 zero()nine()plus()minus()times()dividedBy(),寫出可以進行簡單四則運算的函式。如:zero( plus( three() ) ); 會回傳 3

我的解法

function zero(r) {
  return r === undefined ? 0 : Function( 'return Math.floor(' + 0 + r + ')' )();
}
function one(r) {
  return r === undefined ? 1 : Function( 'return Math.floor(' + 1 + r + ')' )();
}
function two(r) {
  return r === undefined ? 2 : Function( 'return Math.floor(' + 2 + r + ')' )();
}
function three(r) {
  return r === undefined ? 3 : Function( 'return Math.floor(' + 3 + r + ')' )();
}
function four(r) {
  return r === undefined ? 4 : Function( 'return Math.floor(' + 4 + r + ')' )();
}
function five(r) {
  return r === undefined ? 5 : Function( 'return Math.floor(' + 5 + r + ')' )();
}
function six(r) {
  return r === undefined ? 6 : Function( 'return Math.floor(' + 6 + r + ')' )();
}
function seven(r) {
  return r === undefined ? 7 : Function( 'return Math.floor(' + 7 + r + ')' )();
}
function eight(r) {
  return r === undefined ? 8 : Function( 'return Math.floor(' + 8 + r + ')' )();
}
function nine(r) {
  return r === undefined ? 9 : Function( 'return Math.floor(' + 9 + r + ')' )();
}

function plus(p) {
  return '+' + p;
}
function minus(p) {
  return '-' + p;
}
function times(p) {
  return '*' + p;
}
function dividedBy(p) {
  return '/' + p;
}

票選最佳解法

function zero(func)   { return func ? func(0) : 0; };
function one(func)    { return func ? func(1) : 1; };
function two(func)    { return func ? func(2) : 2; };
function three(func)  { return func ? func(3) : 3; };
function four(func)   { return func ? func(4) : 4; };
function five(func)   { return func ? func(5) : 5; };
function six(func)    { return func ? func(6) : 6; };
function seven(func)  { return func ? func(7) : 7; };
function eight(func)  { return func ? func(8) : 8; };
function nine(func)   { return func ? func(9) : 9; };

function plus( b )      { return function( a ) { return a + b; }; };
function minus( b )     { return function( a ) { return a - b; }; };
function times( b )     { return function( a ) { return a * b; }; };
function dividedBy( b ) { return function( a ) { return a / b; }; };

改善點

原本的做法是透過類似 eval() 的方式來解決,用 plus()minus()times()dividedBy() 組成字串後,再用 Functions( 'return ...' )(); 的方式來執行。

但是其實可以透過遞迴函式的方式解決。

遞迴函式一直是我的弱點。

one( plus( two() ) ) 為例,我們可以將整段運算分成兩個階段來看:one( plus() )plus( two() )

one( plus() ) 這段中,會回傳 plus( 1 ),接著變成 plus() 中的 function ( a )a,而原本的 plus( two() ) 則會將 2 帶入 b 中。

console.log() 來捕捉每個步驟的話,會得出下列的結果:

function zero(func)   {
  console.log( 'func is: ' + func );
  return func ? func(0) : 0;
};

function one(func)    {
  console.log( 'func is: ' + func );
  return func ? func(1) : 1;
};

function two(func)    {
  console.log( 'func is: ' + func );
  return func ? func(2) : 2;
};

function three(func)  {
  console.log( 'func is: ' + func );
  return func ? func(3) : 3;
};

function four(func)   {
  console.log( 'func is: ' + func );
  return func ? func(4) : 4;
};

function five(func)   {
  console.log( 'func is: ' + func );
  return func ? func(5) : 5;
};

function six(func)    {
  console.log( 'func is: ' + func );
  return func ? func(6) : 6;
};

function seven(func)  {
  console.log( 'func is: ' + func );
  return func ? func(7) : 7;
};

function eight(func)  {
  console.log( 'func is: ' + func );
  return func ? func(8) : 8;
};

function nine(func)   {
  console.log( 'func is: ' + func );
  return func ? func(9) : 9;
};


function plus( b ) {
  return function( a ) {
    console.log( 'a is: ' + a + ' and b is: ' + b );
    return a + b; };
};

function minus( b ) {
  return function( a ) {
    console.log( 'a is: ' + a + ' and b is: ' + b );
    return a - b; };
};

function times( b ) {
  return function( a ) {
    console.log( 'a is: ' + a + ' and b is: ' + b );
    return a * b; };
};

function dividedBy( b ) {
  return function( a ) {
    console.log( 'a is: ' + a + ' and b is: ' + b );
    return a / b; };
};
Input: one(plus())
Console: func is: function( a ) { console.log( 'a is: ' + a + ' and b is: ' + b );return a + b; }
Console: a is: 1 and b is: undefined
Output: NaN // 這是 1 + undefined 的結果

Input: plus( one() )
Console: func is: undefined // one() 會回傳 1 給 plus(),但不會印出來
Output: ƒ ( a ) { console.log( 'a is: ' + a + ' and b is: ' + b );return a + b; }

Input: one()
Console: func is: undefined // one() 回傳 1 給主控台
Output: 1

Input: plus() // plus() 回傳一個函式給主控台
Output: ƒ ( a ) { console.log( 'a is: ' + a + ' and b is: ' + b );return a + b; }

Input: one(plus(two()))
Console: func is: undefined // two() 回傳 2 給 plus(),不會印出來
Console: func is: function( a ) { console.log( 'a is: ' + a + ' and b is: ' + b );return a + b; }
// one(plus()) 回傳 1 到 function(a) 當中
Console: a is: 1 and b is: 2
Output: 3

參考資料

Eric Chuang
Eric Chuang

正職是廣告行銷人員,因為 Google Tag Manager 的關係開始踏入網站製作的領域,進一步把 WordPress 當成 PHP + HTML + CSS + JavaScript 的學習教材。此外,因為工作的關係,曾經用 Automattic 的 Underscores (_s) 替客戶與公司官網進行全客製化佈景主題開發。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料