-
[알고리즘/자바스크립트] 함수로 계산하기 (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 35four(plus(nine())); // must return 13eight(minus(three())); // must return 5six(dividedBy(two())); // must return 3Ruby:
seven(times(five)) # must return 35four(plus(nine)) # must return 13eight(minus(three)) # must return 5six(divided_by(two)) # must return 3Requirements:
-
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);}반응형'Algorithm' 카테고리의 다른 글
[알고리즘/자바스크립트] 합해서 나눠떨어지는 쌍 찾기 (Divisible Sum Pairs) (0) 2019.05.01 [알고리즘/자바스크립트] 컵 돌리기 게임 (Find Key) (0) 2019.05.01 [알고리즘/자바스크립트] 연속하는 숫자의 합 중 가장 큰 값 구하기 (Maximum subarray sum) (0) 2019.04.28 [알고리즘/자바스크립트] 트리보나치, 피보나치 수열 "재귀함수"로 구하기 (Fibonacci, Tribonacci Sequence) (0) 2019.04.15 [알고리즘/자바스크립트] 배열에서 반대 방향 제거하기 (Directions Reduction) (0) 2019.04.09 COMMENT
-