첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록 solution 함수를 완성해보세요.
| numer1 | denom1 | numer2 | denom2 | result |
|---|---|---|---|---|
| 1 | 2 | 3 | 4 | [5, 4] |
| 9 | 2 | 1 | 3 | [29, 6] |
입출력 예 #1
1 / 2 + 3 / 4 = 5 / 4입니다. 따라서 [5, 4]를 return 합니다.
입출력 예 #2
9 / 2 + 1 / 3 = 29 / 6입니다. 따라서 [29, 6]을 return 합니다.
function solution(numer1, denom1, numer2, denom2) {
var answer = [];
if(denom1 !== denom2) {
answer.push((numer1 * denom2) + (numer2 * denom1));
answer.push(denom1 * denom2);
} else {
answer.push(numer1 + numer2);
answer.push(denom1);
}
for(let i = 2; i <= Math.min(answer[0], answer[1]); i++) {
if(answer[0] % i === 0 && answer[1] % i === 0) {
answer[0] /= i;
answer[1] /= i;
}
}
if(answer[0] % 2 === 0 && answer[1] % 2 === 0) {
answer[0] /= 2;
answer[1] /= 2;
}
return answer;
}
내 풀이는 뭔가 휘갈겨 쓴 느낌이라 지저분하게 나왔다.
처음에 코드를 제출했을 땐 3개의 테스트 케이스에서 실패가 나와서 힌트를 보기 위해 해당 문제의 질문 게시판을 보았다.
거기서 최대공약수를 이용하라는 힌트를 얻고 나서 구글링을 해본 결과
내가 작성한 for문의 조건식이 잘못되었던 것이었다.
최대 공약수를 구하기 위해 for문의 조건식을 i <= Math.min(answer[0], answer[1]) 이렇게 해야 됐다. 그러고 나서 제출해보니 테스트 케이스 5가 실패가 떴다.
이 하나가 뭔 케이스인가 또 질문 게시판을 뒤져보니 4/12, 4/12인 케이스가 반례였다. 4/12+4/12 = 8/12 → 4/6 →2/3 답은 [2, 3]이 된다.
하지만 for문의 조건식에서는 i <= Math.min(8, 12) →i <= 8;
2~8까지 for문을 돌면 처음에 i=2일 때 2로 나눠져서 [4, 6]이 되는데, 그 이후에 i가 3, 4, 5, 6, 7, 8이 되면서 나눌 수 있는 수가 없다.
그래서 2로 나눴을 때 나머지가 0일 경우로 if문을 추가로 작성하여 반례 테스트 케이스 5를 해결했다.
function fnGCD(a, b){
return (a%b)? fnGCD(b, a%b) : b;
}
function solution(denum1, num1, denum2, num2) {
let denum = denum1*num2 + denum2*num1;
let num = num1 * num2;
let gcd = fnGCD(denum, num); //최대공약수
return [denum/gcd, num/gcd];
}
나의 코드와 현저히 비교된다.
예전에 최대공약수 최소공배수 등의 알고리즘을 다 공부했었는데...
지금이라도 머리 속에 넣어두자.
다른 사람의 풀이를 보아하니 재귀문과 삼항연산식을 사용하여 짧게 작성하였는데, 저 식을 풀어서 작성해보겠다.
재귀문 - 최대공약수
function gcd(a, b) { if(b === 0) return a; else return gcd(b, a%b); }