Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

kohigowild

221011 :: [프로그래머스] 이상한 문자 만들기, 점프와 순간 이동, 기능개발 본문

Algorithm

221011 :: [프로그래머스] 이상한 문자 만들기, 점프와 순간 이동, 기능개발

kohi ☕ 2022. 10. 11. 19:14
이상한 문자 만들기
👾 문제 설명
문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

👾 제한 조건
  • 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
  • 첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

 

👾 나의 답안

function solution(s) {
    let words = s.split(" ");
    let arr = [];

    for (let i = 0; i < words.length; i++) {
        for (let j = 0; j < words[i].length; j++) {
            if (j % 2 == 0) {
                arr.push(words[i][j].toUpperCase());
            } else {
                arr.push(words[i][j].toLowerCase());
            }
        }
    }
    return arr.join(" ");
}

 

  • 맨 처음 제출한 답안, 테스트 케이스 실행 결과 T r Y H e L l O W o R l D <= 이렇게 공백 처리가 이상하게 된다.
  • 문자열 s를 공백 기준으로 나눈 배열 words와 문제 조건에 따라 변환한 문자열을 담을 배열 arr을 선언하고 이중 for문을 돈다. j(배열 안의 단어 인덱스)를 2로 나눈 나머지가 0인 경우 대문자 변환, 아니면 소문자 변환을 해서 arr에 push 한다.

 

function solution(s) {
    let result = "";

    for (let i = 0; i < s.length; i++) {
        if (s[i] === " ") result += " ";
        else result += i % 2 == 0 ? s[i].toUpperCase() : s[i].toLowerCase();
    }
    return result;
}

 

  • 두 번째 답안, 테스트 케이스는 통과했는데 채점을 하면 처참해진다.
  • 공백 처리를 하다 보니 코드라인도 너무 길어지고 효율성 문제 때문에 가급적이면 이중 for문을 안 쓰는 게 좋을 것 같아서 방식을 좀 수정했다. 삼항연산자를 사용해서 i를 2로 나눈 나머지가 0이면 result에 대문자를 더하고, 그렇지 않으면 소문자를 더하는 방식이다.
  • 질문하기 게시판에서 모든 예외가 포함된 테스트 케이스("  tRy hello  WORLD    ")라고 해서 한 번 돌려봤는데  이건 또 맞게 출력된다. 생각보다 까다로운 문제다.

 

function solution(s) {
    let result = "";
    let index = 0;

    for (let i = 0; i < s.length; i++) {
        if (s[i] === " ") {
            index = 0;
            result += " ";
        } else {
            result += index % 2 == 0 ? s[i].toUpperCase() : s[i].toLowerCase();
            index++;
        }
    }
    return result;
}

 

  • 이 문제의 교훈은 <<제한 사항을 꼼꼼하게 읽자>> 이다. 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다. ㅎ... 시간 엄청 쓰고 좋은 교훈 얻었다.
  • index 변수를 따로 선언해서 공백인 경우 0으로 초기화, 공백이 아니면 조건에 맞게 대문자 or 소문자를 result에 더하고 index에 1을 더해나간다. 수정하니 쉽게 통과되었다.

 


점프와 순간 이동
👾 문제 설명

OO 연구소는 한 번에 K 칸을 앞으로 점프하거나, (현재까지 온 거리) x 2 에 해당하는 위치로 순간이동을 할 수 있는 특수한 기능을 가진 아이언 슈트를 개발하여 판매하고 있습니다. 이 아이언 슈트는 건전지로 작동되는데, 순간이동을 하면 건전지 사용량이 줄지 않지만, 앞으로 K 칸을 점프하면 K 만큼의 건전지 사용량이 듭니다. 그러므로 아이언 슈트를 착용하고 이동할 때는 순간 이동을 하는 것이 더 효율적입니다. 아이언 슈트 구매자는 아이언 슈트를 착용하고 거리가 N 만큼 떨어져 있는 장소로 가려고 합니다. 단, 건전지 사용량을 줄이기 위해 점프로 이동하는 것은 최소로 하려고 합니다. 아이언 슈트 구매자가 이동하려는 거리 N이 주어졌을 때, 사용해야 하는 건전지 사용량의 최솟값을 return하는 solution 함수를 만들어 주세요.

예를 들어 거리가 5만큼 떨어져 있는 장소로 가려고 합니다.
아이언 슈트를 입고 거리가 5만큼 떨어져 있는 장소로 갈 수 있는 경우의 수는 여러 가지입니다.

  • 처음 위치 0 에서 5 칸을 앞으로 점프하면 바로 도착하지만, 건전지 사용량이 5 만큼 듭니다.
  • 처음 위치 0 에서 2 칸을 앞으로 점프한 다음 순간이동 하면 (현재까지 온 거리 : 2) x 2에 해당하는 위치로 이동할 수 있으므로 위치 4로 이동합니다. 이때 1 칸을 앞으로 점프하면 도착하므로 건전지 사용량이 3 만큼 듭니다.
  • 처음 위치 0 에서 1 칸을 앞으로 점프한 다음 순간이동 하면 (현재까지 온 거리 : 1) x 2에 해당하는 위치로 이동할 수 있으므로 위치 2로 이동됩니다. 이때 다시 순간이동 하면 (현재까지 온 거리 : 2) x 2 만큼 이동할 수 있으므로 위치 4로 이동합니다. 이때 1 칸을 앞으로 점프하면 도착하므로 건전지 사용량이 2 만큼 듭니다.

위의 3가지 경우 거리가 5만큼 떨어져 있는 장소로 가기 위해서 3번째 경우가 건전지 사용량이 가장 적으므로 답은 2가 됩니다.

👾 제한 조건

  • 숫자 N: 1 이상 10억 이하의 자연수
  • 숫자 K: 1 이상의 자연수

 

👾 나의 답안

function solution(n) {
    let ans = 0;

    while (n !== 0) {
        if (n % 2 == 1) {
            n -= 1;
            ans += 1;
        } else if (n % 2 == 0) {
            n /= 2;
        }
    }
    return ans;
}

 

  • 만약 N이 50이라고 가정했을 때, 25만큼 도달해서 순간이동을 하면 된다.
  • 25를 2로 나누면 0으로 나누어 떨어지지 않기 때문에 24에서 1만큼 점프했다고 가정한다. 24에 도달하기 위해서는 12에서 순간이동을 하면 되고, 12에 도달하기 위해서는 6에서 순간이동, 6에 도달하기 위해서는 3에서 순간이동, 3은 2로 나누어 떨어지지 않으므로 2에서 1만큼 점프했다고 가정한다.
  • while 문을 사용해 n이 0이 될 때까지 n이 2로 나누어 떨어지면 2로 나누고, 그렇지 않으면 n에서 1을 빼고 ans에 1을 더한 다음 while 문을 빠져나올 때 ans를 리턴한다.

 

👾 다른 사람의 풀이

function solution(n)
{
    return n.toString(2).replace(/0/g,"").length
}

 

  • n을 2진법으로 변환한 후 1의 개수를 세어도 결과는 같다. 거의 같은 방식으로 접근한 풀이이지만 한끗 차이를 만들어내는 게 정말 어려운 일 같다.

 


기능개발
👾 문제 설명
프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.
또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.
먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.

👾 제한 조건
  • 작업의 개수(progresses, speeds배열의 길이)는 100개 이하입니다.
  • 작업 진도는 100 미만의 자연수입니다.
  • 작업 속도는 100 이하의 자연수입니다.
  • 배포는 하루에 한 번만 할 수 있으며, 하루의 끝에 이루어진다고 가정합니다. 예를 들어 진도율이 95%인 작업의 개발 속도가 하루에 4%라면 배포는 2일 뒤에 이루어집니다.

 

👾 나의 답안

function solution(progresses, speeds) {
    let result = [];
    let count = 0;

    while (progresses.length > 0) {
        for (let i = 0; i < progresses.length; i++) {
            progresses[i] += speeds[i];
        }
        while (true) {
            if (progresses[0] >= 100) {
                progresses.shift();
                speeds.shift();
                count++;
            } else {
                if (count != 0) {
                    result.push(count);
                }
                count = 0;
                break;
            }
        }
    }
    return result;
}

 

  • 완료된 작업의 수를 담을 변수 count와 답을 리턴할 배열 result를 선언한다.
  • progresses 배열 길이가 0보다 큰 동안 반복하고, for loop를 통해 작업을 수행한다. ==> progresses[i]에 speeds[i]을 더함.
  • while문을 사용해 progresses의 배열 값이 100 이상이면 shift로 각각의 배열에서 가장 앞의 값을 삭제하고 count에 1을 더한다.
  • 작업이 완료되지 않은 경우(progresses의 배열 값이 100 미만인 경우) 저장된 count 값을 result에 push하고 count를 0으로 초기화한다.