저장을 습관화
프로그래머스 LV.0 분수의 덧셈 본문
프로그래머스 LV.0 분수의 덧셈
https://school.programmers.co.kr/learn/courses/30/lessons/120808
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
1. 문제 명
분수의 덧셈
2. 문제 설명
첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록 solution 함수를 완성해보세요.
기약함수: 분모와 분자를 최대공약수로 나눈 분수
ex) 27/36 = (27/9)/(36/9) = 3/4
3. 제한 사항
0 <numer1, denom1, numer2, denom2 < 1,000
4. 예시
numer1 | denom1 | numer2 | denom2 | result |
1 | 2 | 3 | 4 | [5, 4] |
9 | 2 | 1 | 3 | [29, 6] |
5. 기본 제공 코드
function solution(numer1, denom1, numer2, denom2) {
var answer = [];
return answer;
}
6. 제출한 내 답
6-1. 제출
function solution(numer1, denom1, numer2, denom2) {
var answer = [];
let resnum = ((numer1 * denom2) + (numer2 * denom1))
let resden = denom1 * denom2;
let gcd = 1;
for (let i = 2; i <= resden; i++) {
if (resnum % i === 0 && resden % i === 0) {
gcd = i;
}
};
resnum = resnum / gcd;
resden = resden / gcd;
return answer = [resnum, resden];
}
6-2. VSC에 작성한 내용
function solution(numer1, denom1, numer2, denom2) {
var answer = []; // 배열 answer 선언
let resnum = ((numer1 * denom2) + (numer2 * denom1)) // 분자 만들기,
// 분수1의 분자와 분수2의 분모를 곱하고, 분수2의 분자와 분수1의 분모를 곱한다.
let resden = denom1 * denom2; // 분수1과 분수2를 곱해 공통의 분모를 만든다.
let gcd = 1; // 최대공약수 선언, 초기값 1
for (let i = 2; i <= resden; i++) {
if (resnum % i === 0 && resden % i === 0) {
gcd = i;
}
};
// 이제 resnum과 resden을 최대공약수로 나누고 싶어
resnum = resnum / gcd;
resden = resden / gcd;
return answer = [resnum, resden];
}
// 요구조건 numer1/denom1 + numer2/denom2 = resnum/resden
// num은 분자, denom은 분모
// 여기서 / 는 나눗셈이 아닌 분수의 표시
// 시도한 방법
// 1) 예시처럼 1/2, 3/4라면 서로 상대방의 분모를 곱하여 4/8, 6/8으로 만든다.
// 2) 그 둘을 더한다. 10/8이 될 것이다.
// 3) 분자와 분모의 최대공약수를 구하여 나눈다. 여기서는 2이다. 5/4가 되었다.
// 4) 이것을 배열 [5, 4]로 표시힌다.
// 테스트
console.log(solution(1, 2, 3, 4));
console.log(solution(9, 2, 1, 3));
7. 특이사항
7-1. 시도한 방법
1) 예시처럼 1/2, 3/4라면 서로 상대방의 분모를 곱하여 4/8, 6/8으로 만든다.
2) 그 둘을 더한다. 10/8이 될 것이다.
3) 분자와 분모의 최대공약수를 구하여 나눈다. 여기서는 2이다. 5/4가 되었다.
4) 이것을 배열 [5, 4]로 표시힌다.
7-2. 헷갈렸던 부분
최대공약수 구하는 방법을 몰라서 검색해서 나온 방법을 참고했다.
JavaScript에서 최대공약수(greatest common divisor)와 최소공배수(least common multiple) 구하는 방법
- 최대공약수
let getGCD = (num1, num2) => {
let gcd = 1; // 변수 gcd의 선언. 초기값은 1
for(let i=2; i<=Math.min(num1, num2); i++ ) {
// 반복문, 변수 i의 초기값은 2이다. i는 num1과 num2중 작은값과 같아질때까지 반복할 것이며,
// 매 사이클마다 i에 1씩 더한다
if(num1 % i === 0 && num2 % i ===0){
// num1에서 i를 나누었을때의 나머지와 num2에서 i를 나누었을때 나머지가 0이라면
gcd = i; // 변수 gcd의 값이 변수 i의 값으로 재지정된다.
// 최대공약수이므로 반복문이 끝날때까지 진행한다. 변수 gcd는 계속해서 바뀔 수 있다.
}
}
return gcd;
}
console.log(getGCD(10, 8)); // 2
console.log(getGCD(29, 6)); // 1
console.log(getGCD(36, 16)); // 4
- 최소공배수
let getLCM = (num1, num2) => {
let lcm = 1; // 변수 lvm 선언, 초기값은 1
while(true){ // 반복문, 참이 될때까지 무한으로 반복한다. break가 필수이다.
if((lcm % num1 === 0) && (lcm % num2 === 0)) {
// 조건문, lcm에서 num1을 나눴을때의 나머지와, lcm에서 num2를 나눴을때의 나머지가 모두 0이라면
break; // 반복문을 종료한다.
}
lcm++; // 매 사이클마다 lcm에 1을 더한다.
}
return lcm;
}
console.log(getLCM(10, 8)); //40
console.log(getLCM(3, 6)); //6
console.log(getLCM(7, 6)); //42
[참고]
JavaScript로 최대공약수(GCD), 최소공배수(LCM) 구하기
최대공약수는 두 수 A와 B의 공통된 약수 중에 가장 큰 정수이다.최대공약수를 구하는 가장 쉬운 방법은 2부터 min(A, B)까지 모든 정수로 나누어보는 방법이다.두 수, 혹은 그 이상의 여러 수의 공
velog.io
위 방법은 참고한 블로그에 사용된 예시일뿐
아래와 같이 훨씬 영리한 방법도 많이 있다.
// 두수 a, b 를 넣는다.
function greatest(a, b) {
// b(나머지)가 0이면 a(직전 나머지)를 반환하고 탈출 (base case)
if (b === 0) return a;
// b를 앞으로 보내고 a % b 를 나눈 나머지(r)을 매개변수로해서 재귀함수로써 호출
return greatest(b, a % b);
}
[참고] https://devbirdfeet.tistory.com/257
화살표 함수와 삼항연산자에 빨리 익숙해져야겠다.
기본 함수 형식에 적응한 후 넘어가면 된다라고 들어서 느긋하게 있었는데
요즘 검색해서 나오는 게시글들은 기본 형식으로 길게 풀어쓰는게 잘 없네
7-3. 반성
쉬운 부분은 어떻게 직접 작성했다 하더라도 정작 제일 중요한 최대공약수 구하는 방법은 남의 코드를 가져다 썼다.
실력을 더 기르자.. 어떻게 하면 좋을지 다시 한번 더 생각해보자..
그 외에도 코드 제출 후 chatgpt에게 코드 검토를 맡겼는데
최대 공약수 구하는 부분에서 아래와 같이 수정해 주었다.
for (let i = Math.min(resnum, resden); i >= 2; i--) {
if (resnum % i === 0 && resden % i === 0) {
gcd = i;
break;
}
}
resnum /= gcd;
resden /= gcd;
1) 변수 i는 resnum과 resden 중 더 작은 수로 삼을 것
나는 이번 테스트에서 무조건 resnum이 resden보다 클것이라 생각하여 기준을 resden로 잡았지만
다시 생각해보니 1/4 + 1/3 = 7/12 처럼 resnum이 작은 경우도 충분히 가능하다.
2) 변수 i를 1씩 줄이고, 최대공약수를 구했다면 break문을 사용하여 불필요한 반복을 줄일것
최대공약수는 그 수가 클 경우가 크므로 큰 수에서부터 하나씩 내려오는게 반복을 더 줄일 수도 있을 것이다.
최대공약수를 찾았다면, 그보다 아래로는 더 내려갈 필요가 없으니 break문으로 빠져나오자
3) resnum = resnum / gcd; 도 간단하게 줄일 수 있음
다음에 다시 참고하자..
8. 다른 사람이 작성한 답
8-1. 재귀함수
function fnGCD(a, b){
return (a%b)? fnGCD(b, a%b) : b;
}
// a에서 b를 나눈 나머지가 1이상이라면 그 나머지 값을 이용하여 다시 한번 fnGCD 함수를 타게되고,
// a에서 b를 나눈 나머지가 0이라면 b가 최대공약수가 되어 return한다.
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]; // 별도의 분자와 분모의 값 재지정 없이
// 그대로 배열에서 계산식을 적용하였다.
}
참 기발한 방법이라고 생각한다.
내 코드에서 몇줄이나 아낄수 있었다.
8-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)]}
이건 보고도 모르겠다
따라도 못하겠다
얘 뭐지
'코딩 테스트 > 프로그래머스 - 자바스크립트' 카테고리의 다른 글
프로그래머스 LV.0 나머지 구하기 (0) | 2023.06.08 |
---|---|
프로그래머스 LV.0 배열 두 배 만들기 (0) | 2023.05.29 |
코딩 테스트 LV.0 숫자 비교하기 (0) | 2023.05.28 |
코딩 테스트 LV.0 두 수의 합, 두 수의 차, 두 수의 곱, 두 수의 나눗셈 (0) | 2023.05.28 |
코딩 테스트 LV.0 몫 구하기 (0) | 2023.05.25 |