[js] 분수의 덧셈 (lv.0, 정답률 61%)

sookyoung.k·2024년 5월 13일
0
post-thumbnail

첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록 solution 함수를 완성해보세요.

제한사항

  • 0 <numer1, denom1, numer2, denom2 < 1,000

나의풀이

function solution(numer1, denom1, numer2, denom2) {
    // 분자, 분모 구하기
  	let numer = numer1 * denom2 + numer2 * denom1;
	let denom = denom1 * denom2;
    
  	// 최소공배수 구하기
  	const getGcd = (a, b) => (a % b == 0 ? b : getGcd(b, a % b));
    let gcd = getGcd(numer, denom);
    
    return [numer / gcd, denom / gcd];
}

그냥 펜 주고 문제 풀라고 하면 개빨리 풀 수 있거든요? ㅠㅠ 이 문제 특히 어려웠어서 정리하려고 했는데 글이 한 세 번 날아가서 개빡쳐있다가 이제 다시 정리한다. 다시 봐도 어려워잉~,,,

  • 먼저 분자와 분모를 구해준다.
    - 분자: 분자에다가 분모를 교차로 곱해주고 더한다.
    • 분모: 분모끼리 곱한다.
  • 여기서 끝나면 .. 좋겟지만 .. 우리는 기약분수로 나타내어야 한다. 최소공배수를 구해야 하는데 이게 진짜 어려웠다... 사실 이 때는 제대로 풀지 못해서 친구의 힘을 빌렸던 것 같다. 필시 과거의 권수경은 그랬을 것. 이해가 안 되면 그냥 외우자.
    - a % b가 0이면 b가 최대공약수가 된다. 그렇지 않을 경우에는 다시 b와 a%b에 대해서 최대공약수를 찾는 과정을 반복한다. 이를 코드로 나타내면 (a, b) => (a % b == 0 ? b : getGcd(b, a % b))가 된다. 이것을 아예 함수로 빼두어서 사용할 수 있게 했다.
  • 계산된 최대 공약수를 사용해 분모와 분자를 나눈 후 이를 배열에 담아 반환한다.

최대공약수(GCD, Greatest Common Divisor)

있어보일라고 영어 약자도 찾아서 가져와봄.

유클리드 알고리즘은 두 수의 최대공약수를 찾는 가장 효율적인 방법 중 하나이다.
: 두 정수 a와 b(a > b)에 대해 a를 b로 나눈 나머지를 r이라고 할 때, a와 b의 최대공약수는 b와 r의 최대공약수와 같다. 이 과정을 나머지가 0이 될 때까지 반복하면 그 때의 b가 a와 b의 최대공약수가 된다.

  1. 초기 단계: 두 수 a와 b를 준비하고, a > b 라고 가정한다.
  2. 나눗셈 단계: a를 b로 나누고 나머지를 r이라고 한다.
  3. 검사 단계: 만약 r이 0이라면, b가 최대공약수가 된다. 그렇지 않다면 다음 단계로 넘어간다.
  4. 재귀 단계: a에 b를, b에 r을 대입하고 2번 단계로 돌아간다.
  5. 종료조건: r이 0이 되었을 때의 b가 최대공약수이다.

예를 들어서 48과 18의 최대공약수를 구해본다.
1. 48을 18로 나누면 나머지는 12가 된다.
2. 18을 12로 나누면 나머지는 6이 된다.
3. 12를 6으로 나누면 나머지는 0이다.

따라서 48과 18의 최대공약수는 6이다.

다른풀이 1

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];
}
  • a % b로 나눈 나머지가 0이 아니라면 b와 a%b를 새로운 매개변수로 하여 fnGCD 함수를 새로 호출한다. 나머지가 0이 되면 b를 반환한다. 앞서 말한 유클리드 알고리즘을 구현한 것이다.

  • 나머지 풀이는 동일하다.

다른풀이 2

var g=(a,b)=>b?g(b,a%b):Math.abs(a),l=(a,b)=>(a*b)/g(a,b),p,q,solution=(a,b,c,d)=>{return p=l(b,d),q=a*p/b+c*p/d,[q/g(p,q),p/g(p,q)]}
  • 최대공약수를 계산하는 g 함수
    - var g=(a,b)=>b?g(b,a%b):Math.abs(a)
    • 유클리드 알고리즘을 사용해서 b가 0이 아닐 때까지 a와 b의 역할을 바꾸고, a%b를 새로운 b로 이용하여 재귀적으로 호출한다. b가 0이 되면 a의 절대값이 두 수의 최대공약수이다.
  • 최소공배수 계산 함수
    - var l=(a,b)=>(a*b)/g(a,b)
    • 두 수 a와 b의 최소공배수를 계산한다. 두 수의 곱을 두 수의 최대공약수로 나누어서 계산한다.
      g(a,b)는 a와 b의 최대공약수
  • 기약분수 형태로 반환
    var solution = (a, b, c, d) => {
    return p = l(b, d), q = a * p / b + c * p / d, [q / g(p, q), p / g(p, q)];
}
- 네 개의 인자를 받아서 a/b와 c/d의 합을 계산하고 기약분수 형태로 반환한다. 
- p는 두 분모 b와 d의 최소공배수
- q는 두 분수의 합의 분자를 계산한다 공통분모 p를 사용하여 각 분수를 동일한 분모로 확장하고 교차로 곱한 후 더해준다 
- 마지막으로 분자 q와 분모 p를 두 수의 최대공약수로 나누어 기약분수 형태로 반환한다 

내가 이걸 한 눈에 이해할 수 있다면 참 좋았겠죠... 어려웠음

profile
영차영차 😎

0개의 댓글