내용이 안 보인다면 쿠키/캐시를 지우고 새로고침 하세요!
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ

게시글

강좌25 - Algorithm - 4달 전 등록

프로그래머스 문제 풀이 Level 1

21번~30번
조회수:
0
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ

21번부터 30번까지 풀어보겠습니다. 모든 문제는 제가 직접 푼 풀이이며, 더 나은 풀이가 있다면 알려주세요~ 못 푼 문제는 끙끙대며 풀어볼테니 스포 금지! 

Level 1 21번~30번

제일 작은 수 제거하기 

[4,3,2,1]이 있다면 가장 작은 1을 제거해서 [4,3,2]를 리턴하면 됩니다.

필터링으로 간단하게 할 수 있을 것 같습니다.

function solution(arr) {
  const min = Math.min(...arr);
  const r = arr.filter(v => v !== min);
  return r.length ? r : [-1];
}

하나 알아두시면 좋은 게 Math.min(...arr)입니다. ...arr은 배열을 펴서 넣는 것입니다. Math.min(arr[0], arr[1], arr[2], ...)과 같습니다.

짝수와 홀수 

function solution(num) {
  return num % 2 ? 'Odd' : 'Even';
}

시간 아깝습니다.

최대공약수와 최소공배수

두 수의 최대공약수와 최소공배수를 구하는 함수입니다.

두 가지를 알아두시는 게 좋은데 바로 최대공약수를 구하는 유클리드 호제법과, 두 수의 곱은 최대공약수와 최소공배수의 곱과 같다는 점입니다. 아니 이걸 어떻게 아냐고요? 여러분 모두 중학교 때 배웠습니다...

function solution(n, m) {
  function u(n, m) { return m % n ? u(m % n, n) : n; }
  const gcd = u(n, m);
  return [gcd, n * m / gcd];
}

u가 유클리드 호제법 함수입니다. 재귀식으로 작성되어 있고요(만약 꼬리재귀가 나중에 된다면 u(m % n, n)을 뒤에 둬야겠죠?). gcd(greatest common divisor)가 최대공약수입니다. 최소공배수는 아까 알려드린 공식대로 구하면 됩니다.

콜라츠 추측 

입력된 수가 짝수면 2로 나누고, 홀수면 3을 곱한 후 1을 더합니다. 이 작업을 반복해서 1까지 몇 번만에 나오는지 구해야 합니다. 6의 경우 6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1로 8번 만에 1이 됩니다. 500회 반복해도 안 되는 경우 -1을 리턴합니다.

일단 조건이 크게 세 개입니다. 500회 반복 초과 경우와, 홀수인 경우, 짝수인 경우입니다. 500회 반복 초과만 별도 처리하고 다른 건 재귀식으로 하면 될 것 같습니다. 

function solution(num, count = 0) {
    return count === 500 
        ? -1 
        : num === 1
            ? count
            : solution(num % 2 ? num * 3 + 1 : num / 2, count + 1);
}

재귀를 사용하면 반복 작업을 줄일 수 있어 편합니다.

평균 구하기  

function solution(arr) {
    return arr.reduce((a, c) => a + c) / arr.length;
}

평균, 곱, 합 등등 뭔가 쌓이는 것들은 다 reduce로 하면 깔끔합니다.

하샤드 수 

x의 자릿수의 합으로 x가 나눠 떨어지면 x는 하샤드 수입니다. 18의 자리수의 합은 1 + 8 = 9이고, 18은 9로 나눠 떨어지므로 18은 하샤드 수인거죠.

일단 자릿수를 쪼개서 더하는 것부터 합시다. split과 reduce면 되죠.

function solution(x) {
    return !(x % String(x).split('').reduce((a, c) => a + c * 1, 0));
}

x를 나눌 수 있으면 0(falsy value)가 나오기 때문에 앞에 !를 붙여 true로 만들었습니다. 문자열을 숫자로 만들기 위해 이번에는 * 1을 한 번 붙여봤습니다. parseInt도 있고 +도 있고 / 1도 있고 다양하게 문자열을 숫자로 만들 수 있습니다.

핸드폰 번호 가리기 

전화번호 뒷 4자리를 빼고 나머지를 전부 *로 바꾸는 문제입니다. 뒷 네자리를 떼내고 앞은 다 *로 바꾼 뒤 다시 붙이면 되겠죠?

function solution(phone_number) {
    return '*'.repeat(phone_number.length - 4) + phone_number.slice(-4);
}

repeat 메서드를 알아두세요. 문자열을 쉽게 반복할 수 있습니다.

정규표현식으로 하면 더 간단하더군요 ㅠㅠ (?=)로 look behind를 썼네요.

function solution(s) {
  return s.replace(/\d(?=\d{4})/g, "*");
}

행렬의 덧셈 

[[1,2],[2,3]]과 [[3,4],[5,6]]이 있으면 [[4,6],[7,9]]가 됩니다. 끼리끼리 더하면 됩니다.

2차원 배열이기 때문에 반복문이 두 번 필요합니다. for을 안 쓰기로 했기 때문에 map을 두 번 연달아 쓰면 됩니다. map을 쓰는 이유는 1,2가 4,6으로, 2,3이 7,9로 1대1로 바뀌기 때문입니다.

function solution(arr1, arr2) {
    return arr1.map((arr, i) => arr.map((v, j) => v + arr2[i][j]));
}

x만큼 간격이 있는 n개의 숫자 

x의 배수를 n개 나열하면 됩니다. 2와 5면 [2,4,6,8,10]이고 -4와 2면 [-4,-8]입니다.

Array fill map을 사용하면 숫자로부터 배열을 쉽게 만들 수 있습니다.

function solution(x, n) {
    return Array(n).fill(x).map((v, i) => (i + 1) * v)
}

map으로 원래의 수와 배수를 1대1로 짝지어주면 됩니다.

직사각형 별찍기 

자바스크립트 문제로는 없어서 그냥 제가 직접 풀었습니다. 왜 안 만들었는지 모르겠네요. 5와 3이 주어지면 5열3행의 별을 찍으면 됩니다.

function solution(a, b) {
  return Array(b).fill().map(() => '*'.repeat(a)).join('\n');
}

\n이 줄바꿈 표시이기때문에 별들로 먼저 배열을 만들고 요소들 사이에 줄바꿈을 넣어줍니다.

다음 시간부터는 Level 2 문제를 풉니다. Level 1보다 확실히 어렵고, 같은 Level 2끼리도 난이도 편차가 좀 있더군요. 노력해보겠습니다!

투표로 게시글에 관해 피드백을 해주시면 많은 도움이 됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright © 2016- 무단 전재 및 재배포 금지

댓글

아직 댓글이 없습니다.