JavaScript - 프로그래머스 레벨 : 1(16) - ORDER BY '정답률'

먹보·2023년 1월 29일
0

1. 숫자 짝꿍

문제 설명 : 두 정수 X, Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 ≤ k ≤ 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(단, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다). X, Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다. X, Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다.

예를 들어, X = 3403이고 Y = 13203이라면, X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로 X = 5525이고 Y = 1255이면 X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5가 3개, Y에는 5가 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.)
두 정수 X, Y가 주어졌을 때, X, Y의 짝꿍을 return하는 solution 함수를 완성해주세요.


// 첫 번 째 풀이법
// function solution(X, Y) {
//     let aNum = [];
//     for (let i = 0 ; i < X.length ; i++){
//             if(Y.match(X[i])){
//                 let j = Y.indexOf(X[i])
//                 Y = Y.slice(0,j) + Y.slice(j+1,Y.length);
//                 aNum.push(X[i])
//             }

//     }
//     let sorted = aNum.sort((a,b) => b-a)
//     if(sorted[0] == 0){
//       return '0'
//     } else{
//       return sorted.length == 0 ? "-1" : sorted.join('')
//     }
// }

function solution(X, Y) {
  const xArr = [...Array(10)].fill(0);
  const yArr = [...Array(10)].fill(0);

  [...X].forEach((item) => xArr[item]++);
  [...Y].forEach((item) => yArr[item]++);

  const answer = xArr.map((item, idx) => {
    if (item !== 0 && yArr[idx] !== 0) {
      return String(idx).repeat(Math.min(item, yArr[idx]));
    }
  });

  const result = answer.reverse().join("");

  return result ? (+result ? result : "0") : "-1";
}

🗒️코멘트 : 사실 최종 풀이 범을 찾는 데 까지 약 1시간이 넘는 시간이 걸렸다....

첫 번째 방식도 작동은 제대로 하지만..소요 시가이 무척 긴 탓에 떨어진다.

간추리는 과정 동안 여러가지 시도를 해보았고.. 기록을 잊어 중간 단계가 싹 사라진 것이 흠이지만 로직을 조금 더 자세히 설명 하자면 다음과 같다.

  1. 우선 숫자가 0 ~ 9까지 총 10개가 존재하기에 10개의 인덱스를 가진 빈 배역 2개를 선언해준다.

  2. 주어진 인자를 ...로 분리해 준 뒤 배열 안에 넣고 각 요소를 인덱스라고 생각하고 그 인덱스의 값들을 하나씩 늘려준다.

  3. X의 요소들로 만들어진 xArr을 맵해주는데 xArr의 요소와 그 요소의 인덱스의 yArr 값이 0 이 아니어야지만 둘 중의 최솟값 만큼 digit이 반복해져서 만들어지겠금 배열을 생성해준다.

  4. 만들어진 배열은 오름차순이기에 뒤집어 준 후 합쳐준다.

사실..아직까지 시각 복잡도를 제대로 계산하지 못하는 점의 한계가 있어 둘 차이의 명확한 시간 복잡도는 모르지만..이것 저것 해본 결과 밑에 것이 되는 것으로 봐서는..밑의 시간 복잡도가 확연히 적은 건 맞는 것 같다.

2. 기사단원의 무기

문제 설명 : 숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다.

각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.

예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다.

기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.


// 1번째 풀이 법
function solution(number, limit, power) {
    let answer = 0;
    let knights = [];
    for (let i = 1 ; i <= number ; i ++){
        knights.push(countDivisors(i))
    }
    knights.map((el,idx)=> el > limit ? knights[idx] = power : el)
    
    return knights.reduce((a,b) => a+b,0);
}

function countDivisors(n) {
  let count = 0;
  for (let i = 1; i <= n; i++) {
    if (n % i === 0) {
      count++;
    }
  }
  return count;
}

//2번째 풀이법
function solution(number, limit, power) {
    let answer = 0;
    for (let i = 1 ; i <= number ; i ++){
        answer += countDivisors(i,limit,power)
    }
    return answer
}

function countDivisors(n,l,p) {
  let c = 0;
  for (let i = 1; i <= n/2; i++) {
    if (n % i === 0) {
      c++;
    }
  }
  return c+1 > l ? p : c+1;
}

🗒️코멘트 : 후...진짜..문제를 푸는 것 자체는 어렵지 않다..

근데..프로그래머스에서 원하는 답을 찾는 데 까지 오래 걸린다. 시간복잡도를 계산 할 줄 모르니 어디에서 줄여나가야 할지 감이 오지 않는다.

최대한 for 문을 줄이고 줄이다 보니..최후의 답안에서 결말을 찾았다.

1번째 풀이법과 2번째 풀이법을 비교해보자.

  1. map 메서드로 실행 해 주었던 기사의 공격력이 제한 수치를 넘을 경우 협약기관에서 정한 공격력을 반환해주는 것을 다른 함수로 따로 빼서 약수의 개수를 찾음과 동시에 진행을 시켰다.

  2. reduce 메서드로 배열 안에 기사의 무기 공격력을 넣어놓고 다 더한 것을 1번의 방법으로 실행하자 마자 다 나오는 결과대로 더할 수 있도록 바꿔 주었다.

  3. 약수의 개수 찾는 법 줄이기.. n의 약수를 찾을 때 솔직히 n 번 돌 필요가 없다..자기 자신을 제외한 약수는 자기 자신의 절반보다 클 수가 없기 때문이다..그래서 딱 절반으로 줄여줬더니..통과가 되었다..

앞으로 꼭!!! 시간 복잡도를 생각하면서 문제를 풀어나가자.

3. 키패드 누르기

문제 설명 : 이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.

  • 엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
  • 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
  • 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
  • 가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.
    - 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.

순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

function solution(numbers, hand) {
    let answer = ""
    const location = {
        1:[0,0],
        2:[1,0],
        3:[2,0],
        4:[0,1],
        5:[1,1],
        6:[2,1],
        7:[0,2],
        8:[1,2],
        9:[2,2],
        0:[1,3],
      left : [0,3],
      right : [2,3]
    }
    const L = [1,4,7];
    const R = [3,6,9];
    for (let i = 0 ; i < numbers.length ; i++){
        if(!L.includes(numbers[i]) && !R.includes(numbers[i])){
            let d = location[numbers[i]]
            let lL = Math.abs(location["left"][0]-d[0]) + Math.abs(location["left"][1]-d[1])
            let rL = Math.abs(location["right"][0]-d[0]) + Math.abs(location["right"][1]-d[1])
            if (lL > rL){
                answer += 'R'
                location["right"] = location[numbers[i]]
            } else if (rL > lL){
                answer += 'L'
                location['left'] = location[numbers[i]]
            } else if (lL == rL){
                answer += hand[0].toUpperCase()
                location[hand] = location[numbers[i]]
                
            }
        } else if (L.includes(numbers[i])){
            answer += 'L'
            location["left"] = location[numbers[i]]
        } else if (R.includes(numbers[i])){
            answer += 'R'
            location["right"] = location[numbers[i]]
        }
    }
    return answer;
}

🗒️코멘트 : 문제 자체는 쉬웠지만...코드는..단순하지 않았다..

profile
🍖먹은 만큼 성장하는 개발자👩‍💻

0개의 댓글