-
[알고리즘/자바스크립트] 함수로 계산하기 (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); }
반응형'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
-