본문 바로가기
codingtest

[programmers] 다항식 더하기, 합성수 찾기, 머쓱이보다 키 큰 사람, 분수의 덧셈, 두 수의 나눗셈

by 안자두 2023. 3. 23.

📝 [Lv0] 다항식 더하기

👀 문제 설명

한 개 이상의 항의 합으로 이루어진 식을 다항식이라고 합니다. 다항식을 계산할 때는 동류항끼리 계산해 정리합니다. 덧셈으로 이루어진 다항식 polynomial이 매개변수로 주어질 때, 동류항끼리 더한 결괏값을 문자열로 return 하도록 solution 함수를 완성해보세요. 같은 식이라면 가장 짧은 수식을 return 합니다.

 

🚨 제한 사항

  • 0 < polynomial에 있는 수 < 100
  • polynomial에 변수는 'x'만 존재합니다.
  • polynomial은 0부터 9까지의 정수, 공백, ‘x’, ‘+'로 이루어져 있습니다.
  • 항과 연산기호 사이에는 항상 공백이 존재합니다.
  • 공백은 연속되지 않으며 시작이나 끝에는 공백이 없습니다.
  • 하나의 항에서 변수가 숫자 앞에 오는 경우는 없습니다.
  • " + 3xx + + x7 + "와 같은 잘못된 입력은 주어지지 않습니다.
  • "012x + 001"처럼 0을 제외하고는 0으로 시작하는 수는 없습니다.
  • 문자와 숫자 사이의 곱하기는 생략합니다.
  • polynomial에는 일차 항과 상수항만 존재합니다.
  • 계수 1은 생략합니다.
  • 결괏값에 상수항은 마지막에 둡니다.
  • 0 < polynomial의 길이 < 50

 

💻 입출력 예

polynomial result
"3x + 7 + x" "4x + 7"
"x + x + x" "3x"

 

✨ 풀이 설명

문제 자체는 어렵지 않지만 정답으로 변환하는 과정이 다른 Lv0 문제들에 비해 까다로웠다.

' + '를 기준으로 문자열을 분리해 배열화하여 [0, 0]으로 초기화 된 reduce()로 각 분리된 문자열이 'x'를 포함하고 있는지 확인해 주었다.
이 과정에서 split()을 사용해 주었는데, 만약 'x'를 포함한다면 'x'를 기준으로 문자열이 분리될 것이고, 아니라면 분리되지 않을 것이다.
예를 들어, ['7x', 'x', '4']라는 배열이 생긴다면 각각은 '7' '', '' '', '4'가 될 것이다.
즉, 'x'가 포함되어 있다면 split() 이후의 길이가 2, 포함되어 있지 않다면 1이 된다.
이를 이용하여 길이가 1일 경우에는 해당 숫자를 reduce()의 arr 첫 번째 인덱스에 더해주었다.
그리고 길이가 1이 아닌 경우, 일차항이라는 뜻이므로 split()으로 나뉜 문자 중, 계수에 해당하는 앞부분을 더해주었다.
이때, 빈 문자열이면 계수가 1이라는 뜻이므로 1을 더해주었다.

이렇게 각 항의 계수들이 반환된 list라는 배열에서 일차항의 값을 조금 변형해 주었다.
일차항의 계수가 0일 경우는 빈 문자열, 1일 경우는 'x', 그 외에는 계수에 'x'를 더한 값으로 바꿔주었다.

list 배열을 filter()로 유효한 값만을 뽑아주었는데, 이렇게 한 이유는 각 항의 값이 없을 경우를 배제하기 위해서이다.
만약 일차항의 값이 없다면 빈 문자열이 들어있을 것이고, 상수항의 값이 없다면 0이 들어있을 것이다.
이는 falsy한 값이기 때문에 boolean으로 형변환을 하면 false가 된다. 
따라서, filter()에 걸러지게 되고 새로 생성된 배열은 존재하는 항만 반환된다. 이 배열의 크기가 1 이상일 경우에는 join()으로 가운데 ' + '가 추가된 문자열이 반환되고, 1일 경우에는 해당 배열의 값이 그대로 문자열로 반환이 된다.

일차항의 계수가 1일 때, 표시를 해주지 않는 점이 이번 문제를 복잡하게 만든 것 같다. 그 점을 제외한다면 더 쉽게 해결했을 것 같다.

 

🕵️‍♂️ 코드

function solution(polynomial) {
  const list = polynomial.split(' + ').reduce((arr, expr) => {
    const coef = expr.split('x');
    if (coef.length === 1) arr[1] += +coef[0];
    else arr[0] += coef[0] ? +coef[0] : 1;
    return arr;
  }, [0, 0]);

  list[0] = list[0] ? list[0] === 1 ? 'x' : list[0] + 'x' : '';

  return list.filter(item => item).join(' + ');
}
 
 

📝 [Lv0] 합성수 찾기

👀 문제 설명

약수의 개수가 세 개 이상인 수를 합성수라고 합니다. 자연수 n이 매개변수로 주어질 때 n이하의 합성수의 개수를 return하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • 1 ≤ n ≤ 100

 

💻 입출력 예

n result
10 5
15 8

 

✨ 풀이 설명

합성수는 약수의 개수가 세 개 이상인 수를 말한다. 즉, 약수의 개수가 1과 본인 자신, 2개 만을 갖는 소수가 아닌 수를 말한다(1을 제외하고).
문제의 제한 사항이 1 이상이었기 때문에 1을 포함하지 않도록 주의해야 한다.

전체 숫자들 중, 1과 소수를 빼면 합성수의 개수가 나온다.
그렇기 때문에 소수를 구하는 함수를 따로 만들어 주었다. 2부터 num의 제곱근까지의 수를 나눴을 때, 나누어진다면 약수가 존재한다는 뜻이다. 따라서 그 수는 소수가 아니므로 false를 반환해 주었고, 약수가 존재하지 않다면 소수라는 뜻으로 true를 반환해 주었다.

이제 1을 제외하고 계산할 것이기 때문에 n-1 크기의 배열을 filter()를 사용해 인덱스를 수로 이용해 값을 구해줄 것이다.
인덱스는 0부터 시작하고 나는 1을 제외한 2부터 시작할 것이기 때문에 i + 2를 isPrime() 함수에 넣어 해당 수가 소수인지 확인해 주었다. 구해야 할 것은 소수가 아닌 합성수이기 때문에 isPrime()에서 false가 반환된 수를 구하면 된다.
이렇게 생성된 새로운 배열의 길이를 구하면 합성수의 개수가 된다.

 

🕵️‍♂️ 코드

const isPrime = num => {
  for (let i = 2; i <= Math.sqrt(num); i++) {
    if (!(num % i)) return false;
  }
  return true;
}

function solution(n) {
  return new Array(n - 1).fill().filter((_, i) => !isPrime(i + 2)).length;
}

 


📝 [Lv0] 머쓱이보다 키 큰 사람

👀 문제 설명

머쓱이는 학교에서 키 순으로 줄을 설 때 몇 번째로 서야 하는지 궁금해졌습니다. 머쓱이네 반 친구들의 키가 담긴 정수 배열 array와 머쓱이의 키 height가 매개변수로 주어질 때, 머쓱이보다 키 큰 사람 수를 return 하도록 solution 함수를 완성해보세요.

 

🚨 제한 사항

  • 1 ≤ array의 길이 ≤ 100
  • 1 ≤ height ≤ 200
  • 1 ≤ array의 원소 ≤ 200

 

💻 입출력 예

array height result
[149, 180, 192, 170] 167 3
[180, 120, 140] 190 0

 

✨ 풀이 설명

머쓱이보다 키 큰 친구들을 찾기 위해 친구들 사이에 머쓱이를 넣어주었다. 그다음 sort()를 사용해 친구들을 키가 큰 순서대로 정렬해 주었고, 이곳에서 머쓱이가 몇 번째에 위치해 있는지 구해주었다.

indexOf()를 사용하면 해당 배열에서 height가 몇 번째에 위치해 있는지 알 수 있다.
만약 정렬된 배열 [180, 178, 160, 159, 157]이 있다고 할 때, 머쓱이의 키가 160이라면 머쓱이는 index 2에 위치해 있을 것이다. 즉, 머쓱이보다 키가 큰 친구는 머쓱이 앞에 위치해 있는 친구들이기 때문에 index 0과 1 2명임을 알 수 있다.

 

🕵️‍♂️ 코드

function solution(array, height) {
  return [...array, height].sort((prev, next) => next - prev).indexOf(height);
}

 


📝 [Lv0] 분수의 덧셈

👀 문제 설명

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

 

🚨 제한 사항

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

 

💻 입출력 예

numer1 denom1 numer2 denom2 result
1 2 3 4 [5, 4]
9 2 1 3 [29, 6]

 

✨ 풀이 설명

수학문제를 푸는 느낌으로 풀이를 해보았다. 첫 번째 분수와 두 번째 분수의 분모를 곱하여 분모를 통일시켜 준 후, 각 분자에도 상대 분수의 분모를 곱하여 더해 주었다.

그런 다음, 두 분수를 더한 값을 기약 분수로 만들기 위해 분자와 분모의 최대공약수를 구해 각각을 나누어 주었다.
GCD 함수는 이 문제를 풀 때 사용했던 코드이다.

 

🕵️‍♂️ 코드

function solution(numer1, denom1, numer2, denom2) {
  const denom = denom1 * denom2;
  const numer = (numer1 * denom2) + (numer2 * denom1);

  const GCD = (num1, num2) => num2 ? GCD(num2, num1 % num2) : num1;

  return [numer / GCD(numer, denom), denom / GCD(numer, denom)];
}

 


📝 [Lv0] 두 수의 나눗셈

👀 문제 설명

정수 num1 num2가 매개변수로 주어질 때, num1 num2로 나눈 값에 1,000을 곱한 후 정수 부분을 return 하도록 soltuion 함수를 완성해주세요.

 

🚨 제한 사항

  • 0 < num1 ≤ 100
  • 0 < num2 ≤ 100

 

💻 입출력 예

num1 num2 result
3 2 1500
7 3 2333
1 16 62

 

✨ 풀이 설명

num1을 num2로 나눈 후, 1000을 곱한 수를 버림 해 주었다.

다른 풀이를 보니 Math.trunc()라는 함수를 볼 수 있었다.
나는 처음 보는 함수였는데, 이 함수는 주어진 값의 소수 부분을 제거하고 숫자의 정수 부분을 반환해 주는, 이번 문제에서 요구한 사항을 딱 해결해 줄 수 있는 함수였다.

 

🕵️‍♂️ 코드

function solution(num1, num2) {
  return Math.floor(num1 / num2 * 10e2);
}

 

728x90