ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [알고리즘/자바스크립트] 함수로 계산하기 (Calculating with Functions)
    Algorithm 2019. 4. 29. 15:03

    -해당 문제는 codewars사이트의 level5 문제입니다. (1~8단계 중 8단계가 가장 쉬운 레벨)-

    [문제] This time we want to write calculations using functions and get the results. Let's have a look at some examples:

     

    JavaScript:

    seven(times(five())); // must return 35
    four(plus(nine())); // must return 13
    eight(minus(three())); // must return 5
    six(dividedBy(two())); // must return 3

     

    Ruby:

    seven(times(five)) # must return 35 
    four(plus(nine)) # must return 13 
    eight(minus(three)) # must return 5 
    six(divided_by(two)) # must return 3

     

    Requirements:

    • There must be a function for each number from 0 ("zero") to 9 ("nine")

    • There must be a function for each of the following mathematical operations: plus, minus, times, dividedBy (divided_by in Ruby)

    • Each calculation consist of exactly one operation and two numbers

    • The most outer function represents the left operand, the most inner function represents the right operand

    • Divison should be integer division, e.g eight(dividedBy(three()))/eight(divided_by(three)) should return 2, not 2.666666...


    [해석] 함수를 이용하여 계산을 하려고 한다. 위의 예제 코드를 참고하면 된다.

    필요한 사항들)

    • 0("zero")부터 9("nine")까지 각각의 숫자에 대응하는 함수가 반드시 있어야 한다.
    • plus, minus, times, dividedBy 이 4가지 산술연산자에 대응하는 함수가 반드시 있어야 한다.
    • 모든 계산은 하나의 연산자와 두 개의 숫자로 구성되어 있다.
    • 가장 바깥쪽 함수는 왼쪽 항을 의미하고 가장 안쪽 함수는 오른쪽 항을 의미한다.
    • 나눗셈의 결과는 반드시 정수값이어야 한다. eight(dividedBy(three()))를 했을 때 결과값은 2.666666...이 아닌 2여야 한다.

     

    일단 가장 먼저 문제를 푼 방법은 다음과 같다.

    function zero(oper) {
    	var num = '0';
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function one(oper) {
    	var num = 1;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function two(oper) {
    	var num = 2;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function three(oper) {
    	var num = 3;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function four(oper) {
    	var num = 4;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function five(oper) {
    	var num = 5;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function six(oper) {
    	var num = 6;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function seven(oper) {
    	var num = 7;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function eight(oper) {
    	var num = 8;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    function nine(oper) {
    	var num = 9;
    	return (oper) ? parseInt(eval(num + oper)) : num;
    }
    
    function plus(num) {
    	if(num) { return '+' + num; }
    }
    function minus(num) {
    	if(num) { return '-' + num; }
    }
    function times(num) {
    	if(num) { return '*' + num; }
    }
    function dividedBy(num) {
    	if(num) { return '/' + num; }
    }

    이제 이 코드에서 저 똑같이 반복되는 코드들을 함수로 빼고

    eval()을 쓰지 않고 연산해보기로 했다.

     

    function zero(oper) {
    	return operate(oper, 0);
    }
    function one(oper) {
    	return operate(oper, 1);
    }
    function two(oper) {
    	return operate(oper, 2);
    }
    function three(oper) {
    	return operate(oper, 3);
    }
    function four(oper) {
    	return operate(oper, 4);
    }
    function five(oper) {
    	return operate(oper, 5);
    }
    function six(oper) {
    	return operate(oper, 6);
    }
    function seven(oper) {
    	return operate(oper, 7);
    }
    function eight(oper) {
    	return operate(oper, 8);
    }
    function nine(oper) {
    	return operate(oper, 9);
    }
    function operate(rightOp, num) {
    	if(rightOp) {
    		return rightOp(num)
    	} else {
    		return num;
    	}
    }
    function plus(right) {
    	return function(left) {
    		return left + right;
    	}
    }
    function minus(right) {
    	return function(left) {
    		return left - right;
    	}
    }
    function times(right) {
    	return function(left) {
    		return left * right;
    	}
    }
    function dividedBy(right) {
    	return function(left) {
    		return parseInt(left / right);
    	}
    }

    four(plus(nine()));을 실행시킨다고 했을 때,

    four()함수를 실행시키면 plus()함수와 숫자 4가 operate()함수로 전달된다.

    operate함수에서 rightOp에는 plus()함수의 return값인 function(left) {} 함수가 전달되는데,

    이 함수가 전달되어 rightOp는 truthy이므로 if문을 충족하여

    rightOp(num)을 실행시킨다. 그러면 left값으로 4가 할당되고 plus(right)에 right으로 전달된 9가

    곱셈 연산을 하게 되어 4*9 = 36을 최종 return하게 된다.

     

     

    이제 이걸 좀 더 간단하게 아래와 같이 줄일 수 있다.

    var zero = operate(0);
    var one = operate(1);
    var two = operate(2);
    var three = operate(3);
    var four = operate(4);
    var five = operate(5);
    var six = operate(6);
    var seven = operate(7);
    var eight = operate(8);
    var nine = operate(9);
    
    function operate (num) {
    	return function (oper) {
    		return (oper) ? oper(num) : num;
    	}
    }
    function plus(right) {
    	return function(left) {
    		return left + right;
    	}
    }
    function minus(right) {
    	return function(left) {
    		return left - right;
    	}
    }
    function times(right) {
    	return function(left) {
    		return left * right;
    	}
    }
    function dividedBy(right) {
    	return function(left) {
    		return parseInt(left / right);
    	}
    }

     

    저 숫자 zero, one, two... 이렇게 각각을 변수로 만들고 싶지 않다면

    배열에 넣어서 반복문을 돌리는 방법도 있다.

    ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
    .forEach(function(name, index) {
    	this[name] = operate(index);
    });
    function operate (num) {
    	return function (oper) {
    		return (oper) ? oper(num) : num;
    	}
    }
    function plus(right) {
    	return function(left) {
    		return left + right;
    	}
    }
    function minus(right) {
    	return function(left) {
    		return left - right;
    	}
    }
    function times(right) {
    	return function(left) {
    		return left * right;
    	}
    }
    function dividedBy(right) {
    	return function(left) {
    		return parseInt(left / right);
    	}
    }

     

    마지막으로 위 코드들을 화살표 함수로 좀 더 간결하게 표현하면 다음과 같다.

    ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
    .forEach(function(name, index) {
    	this[name] = operate(index);
    })
    function operate (num) {
    	return (oper) => (oper) ? oper(num) : num;
    }
    function plus(right) {
    	return (left) => left + right;
    }
    function minus(right) {
    	return (left) => left - right;
    }
    function times(right) {
    	return (left) => left * right;
    }
    function dividedBy(right) {
    	return (left) => parseInt(left / right);
    }

     

    반응형

    COMMENT