문제 설명

프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.

또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.

먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 때 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.

제한 사항

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

입출력 예

progresses speeds return
[93, 30, 55] [1, 30, 5] [2, 1]
[95, 90, 99, 99, 80, 99] [1, 1, 1, 1, 1, 1] [1, 3, 2]
입출력 예 설명

입출력 예 #1
첫 번째 기능은 93% 완료되어 있고 하루에 1%씩 작업이 가능하므로 7일간 작업 후 배포가 가능합니다.
두 번째 기능은 30%가 완료되어 있고 하루에 30%씩 작업이 가능하므로 3일간 작업 후 배포가 가능합니다. 하지만 이전 첫 번째 기능이 아직 완성된 상태가 아니기 때문에 첫 번째 기능이 배포되는 7일째 배포됩니다.
세 번째 기능은 55%가 완료되어 있고 하루에 5%씩 작업이 가능하므로 9일간 작업 후 배포가 가능합니다.

따라서 7일째에 2개의 기능, 9일째에 1개의 기능이 배포됩니다.

입출력 예 #2
모든 기능이 하루에 1%씩 작업이 가능하므로, 작업이 끝나기까지 남은 일수는 각각 5일, 10일, 1일, 1일, 20일, 1일입니다. 어떤 기능이 먼저 완성되었더라도 앞에 있는 모든 기능이 완성되지 않으면 배포가 불가능합니다.

따라서 5일째에 1개의 기능, 10일째에 3개의 기능, 20일째에 2개의 기능이 배포됩니다.


나의 코드

function solution(progresses, speeds) {
    let answer = [];
    let temp = [0];
    let result = [];
    
    for (let i=0; i<progresses.length; i++) {
        let remain = 100 - progresses[i];
        let nameoji = remain % speeds[i];
        let mok = nameoji==0 ? parseInt(remain/speeds[i]) : parseInt(remain/speeds[i])+1;

        answer.push(mok);
    }
    
    let head = answer[0];
    for (let i=0; i<answer.length-1; i++) {
        if (head < answer[i+1]) {
            head = answer[i+1];
            temp.push(answer.indexOf(head));
        }
    }
    temp.push(answer.length);
    
    for (let i=0; i<temp.length-1; i++) {
        result.push(temp[i+1]-temp[i]);
    }
    
    return result;
}

문제 풀이

우선 각 기능마다 작업하는데 걸리는 시간을 구한다. => answer

그리고 answer배열에서 배포하는 날짜들을 다시 구한다 => temp

마지막으로 temp배열에서 오른쪽 수에서 왼쪽 수를 뺀다 => result

위와 같이 정답을 구하기 위해 옆의 수와 비교했기 때문에 temp배열 마지막에 answer.length를 삽입해 준 것이다.

오늘의 공부

반복문도 너무 많이 사용한 것 같고, 코드를 딱히 효율적으로 짠 것 같지도 않다... 추후 리팩토링 필요!

작업일수를 구한 후, 몇개의 기능이 배포되는지 구현하는게 쉽게 풀리지 않았다ㅠ 머리로는 뚝딱인데 코드로 정리가 안된다ㅠㅠ

shift()는 객체의 맨 앞 요소를 가져오고, pop()은 맨 뒤 요소를 가져온다! 그리고 둘다 원본 배열을 바꾼다.

[문제 설명]

게임개발자인 "죠르디"는 크레인 인형뽑기 기계를 모바일 게임으로 만들려고 합니다.
"죠르디"는 게임의 재미를 높이기 위해 화면 구성과 규칙을 다음과 같이 게임 로직에 반영하려고 합니다.

게임 화면은 "1 x 1" 크기의 칸들로 이루어진 "N x N" 크기의 정사각 격자이며 위쪽에는 크레인이 있고 오른쪽에는 바구니가 있습니다. (위 그림은 "5 x 5" 크기의 예시입니다). 각 격자 칸에는 다양한 인형이 들어 있으며 인형이 없는 칸은 빈칸입니다. 모든 인형은 "1 x 1" 크기의 격자 한 칸을 차지하며 격자의 가장 아래 칸부터 차곡차곡 쌓여 있습니다. 게임 사용자는 크레인을 좌우로 움직여서 멈춘 위치에서 가장 위에 있는 인형을 집어 올릴 수 있습니다. 집어 올린 인형은 바구니에 쌓이게 되는 데, 이때 바구니의 가장 아래 칸부터 인형이 순서대로 쌓이게 됩니다. 다음 그림은 [1번, 5번, 3번] 위치에서 순서대로 인형을 집어 올려 바구니에 담은 모습입니다.

만약 같은 모양의 인형 두 개가 바구니에 연속해서 쌓이게 되면 두 인형은 터뜨려지면서 바구니에서 사라지게 됩니다. 위 상태에서 이어서 [5번] 위치에서 인형을 집어 바구니에 쌓으면 같은 모양 인형 두 개가 없어집니다.

크레인 작동 시 인형이 집어지지 않는 경우는 없으나 만약 인형이 없는 곳에서 크레인을 작동시키는 경우에는 아무런 일도 일어나지 않습니다. 또한 바구니는 모든 인형이 들어갈 수 있을 만큼 충분히 크다고 가정합니다. (그림에서는 화면표시 제약으로 5칸만으로 표현하였음)

게임 화면의 격자의 상태가 담긴 2차원 배열 board와 인형을 집기 위해 크레인을 작동시킨 위치가 담긴 배열 moves가 매개변수로 주어질 때, 크레인을 모두 작동시킨 후 터트려져 사라진 인형의 개수를 return 하도록 solution 함수를 완성해주세요.

[제한사항]
  • board 배열은 2차원 배열로 크기는 "5 x 5" 이상 "30 x 30" 이하입니다.
  • board의 각 칸에는 0 이상 100 이하인 정수가 담겨있습니다.
    • 0은 빈 칸을 나타냅니다.
    • 1 ~ 100의 각 숫자는 각기 다른 인형의 모양을 의미하며 같은 숫자는 같은 모양의 인형을 나타냅니다.
  • moves 배열의 크기는 1 이상 1,000 이하입니다.
  • moves 배열 각 원소들의 값은 1 이상이며 board 배열의 가로 크기 이하인 자연수입니다.
[입출력 예]
board moves result
[[0,0,0,0,0],[0,0,1,0,3],[0,2,5,0,1],[4,2,4,4,2],[3,5,1,3,1]] [1,5,3,5,1,2,1,4] 4

나의 풀이

function solution(board, moves) {
    var answer = 0;
    var basket = [];
    var boom = [];
 
    for (let j of moves) {
        for (let i=0; i<board.length; i++) {
            if (board[i][j-1] != 0) {
                basket.push(board[i][j-1]);
                board[i][j-1] = 0;
                break
            }
        }
    }

    var n = 0;
    while (n < basket.length) {
        if (basket[n] == basket[n+1]) {
            answer += 2;
            boom = basket.splice(n, 2);
            n = 0;
        } else {
            n += 1;
        }
    }
    
    return answer;
}

 

오늘의 공부

처음에는 계속 테케 1,2번이 틀렸었는데, 질문하기에 올려준 테케를 입력해봐도 기존 코드는 통과가 되었다. while문이 잘못된 것 같아서 수정하다가 두 인형이 터지고 나서  basket 위치를 잘 못잡는 것을 알게되었다!

    var n = 0;
    while(n < basket.length) {
        n++;
        basket.forEach((v,i) => {
            if (basket[i] == basket[i+1]) {
                answer.push(basket[i])
                boom = basket.splice(i, 2);
            }
        })
    }

참고로 테케 1,2번이 실패떴을 때는 while문을 위와 같이 작성했었다.

문제 설명

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

  • 1478 → "one4seveneight"
  • 234567 → "23four5six7"
  • 10203 → "1zerotwozero3"

이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.

숫자 영단어
0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine

 

제한사항
  • 1 ≤ s의 길이 ≤ 50
  • s가 "zero" 또는 "0"으로 시작하는 경우는 주어지지 않습니다.
  • return 값이 1 이상 2,000,000,000 이하의 정수가 되는 올바른 입력만 s로 주어집니다.
입출력 예
s result
"one4seveneight" 1478
"23four5six7" 234567
"2three45sixseven" 234567
"123" 123

나의 풀이

function solution(s) {
    var arr = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
    
    arr.forEach((v,i) => {
        var text = v;
        var regexAll = new RegExp(text, "g");
        s = s.replace(regexAll, i);
    })

    s = parseInt(s)
    return s
}

 

풀이 설명

영단어가 담긴 배열 arr을 만들고, forEach문을 사용한다. 배열의 각 값들을 변수 text로 받아와서 전역으로 ("g") 검사해주는데 이때 생성자 함수를 사용해 정규표현식 regexAll을 동적으로 계속 바꿔주는 것이다.

이렇게 만들어진 정규표현식을 사용하여 문자열 s를 검사하는데 일치한다면 해당 단어를 i로 바꿔준다. 이때 i는 인덱스이므로 영단어에 매칭되는 숫자로 바꿔줄 수 있는 것이다.

 

오늘의 공부

정규식 패턴이 변경되는 경우, 생성자 함수를 사용해 동적으로 정규표현식을 만들어보았다. 문제를 읽고나서 영단어를 비교해가면서 검사한 다음에 숫자로 바꿔주면 될 것 같은데! 같지만!!! 생성자 함수를 사용해 정규표현식을 만들어보지 않아서 검색을 좀 해보고 통과할 수 있었다. 

생성자 함수에 대해서 추가적으로 공부를 해야겠다. 할 것이다!

 

[문제 설명]

카카오에 입사한 신입 개발자 네오는 "카카오계정개발팀"에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. "네오"에게 주어진 첫 업무는 새로 가입하는 유저들이 카카오 아이디 규칙에 맞지 않는 아이디를 입력했을 때, 입력된 아이디와 유사하면서 규칙에 맞는 아이디를 추천해주는 프로그램을 개발하는 것입니다.
다음은 카카오 아이디의 규칙입니다.

  • 아이디의 길이는 3자 이상 15자 이하여야 합니다.
  • 아이디는 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.) 문자만 사용할 수 있습니다.
  • 단, 마침표(.)는 처음과 끝에 사용할 수 없으며 또한 연속으로 사용할 수 없습니다.

"네오"는 다음과 같이 7단계의 순차적인 처리 과정을 통해 신규 유저가 입력한 아이디가 카카오 아이디 규칙에 맞는 지 검사하고 규칙에 맞지 않은 경우 규칙에 맞는 새로운 아이디를 추천해 주려고 합니다.
신규 유저가 입력한 아이디가 new_id 라고 한다면,

1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
     만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

예를 들어, new_id 값이 "...!@BaT#*..y.abcdefghijklm" 라면, 위 7단계를 거치고 나면 new_id는 아래와 같이 변경됩니다.

1단계 대문자 'B'와 'T'가 소문자 'b'와 't'로 바뀌었습니다.
"...!@BaT#*..y.abcdefghijklm"  "...!@bat#*..y.abcdefghijklm"

2단계 '!', '@', '#', '*' 문자가 제거되었습니다.
"...!@bat#*..y.abcdefghijklm"  "...bat..y.abcdefghijklm"

3단계 '...'와 '..' 가 '.'로 바뀌었습니다.
"...bat..y.abcdefghijklm"  ".bat.y.abcdefghijklm"

4단계 아이디의 처음에 위치한 '.'가 제거되었습니다.
".bat.y.abcdefghijklm"  "bat.y.abcdefghijklm"

5단계 아이디가 빈 문자열이 아니므로 변화가 없습니다.
"bat.y.abcdefghijklm"  "bat.y.abcdefghijklm"

6단계 아이디의 길이가 16자 이상이므로, 처음 15자를 제외한 나머지 문자들이 제거되었습니다.
"bat.y.abcdefghijklm"  "bat.y.abcdefghi"

7단계 아이디의 길이가 2자 이하가 아니므로 변화가 없습니다.
"bat.y.abcdefghi"  "bat.y.abcdefghi"

따라서 신규 유저가 입력한 new_id가 "...!@BaT#*..y.abcdefghijklm"일 때, 네오의 프로그램이 추천하는 새로운 아이디는 "bat.y.abcdefghi" 입니다.


[문제]

신규 유저가 입력한 아이디를 나타내는 new_id가 매개변수로 주어질 때, "네오"가 설계한 7단계의 처리 과정을 거친 후의 추천 아이디를 return 하도록 solution 함수를 완성해 주세요.

[제한사항]

new_id는 길이 1 이상 1,000 이하인 문자열입니다.
new_id는 알파벳 대문자, 알파벳 소문자, 숫자, 특수문자로 구성되어 있습니다.
new_id에 나타날 수 있는 특수문자는 -_.~!@#$%^&*()=+[{]}:?,<>/ 로 한정됩니다.

[입출력 예]
no new_id result
예1 "...!@BaT#*..y.abcdefghijklm" "bat.y.abcdefghi"
예2 "z-+.^." "z--"
예3 "=.=" "aaa"
예4 "123_.def" "123_.def"
예5 "abcdefghijklmn.p" "abcdefghijklmn"

나의 풀이

function solution(new_id) {
    var isReg = /[a-z0-9]/;

    // 1. 소문자로 치환
    var str = new_id.toLowerCase();

    // 2. 문자 제외
    for (let i of str) {
        if ( !(isReg.test(i) || i==='-' || i==='_' || i==='.') ) {
            str = str.replace(i, '')
        } 
    }

    // 3. 마침표가 2번이상
    var str = str.replace(/\.+/g,'.')

    // 4. 앞뒤 마침표 제거
    if (str.slice(0, 1) == '.') {
        str = str.replace('.', '')
    }
    if (str.slice(-1) == '.') {
        str = str.slice(0, -1)
    }

    // 5. 빈 문자열
    if (str.length == 0) {
        str = 'a'
    }

    // 6. 15자리까지만 출력
    if (str.length >= 16) {
        str = str.slice(0, 15);

        if (str.slice(-1) == '.') {
            str = str.slice(0, -1)
        }
    }

    // 7. 2자 이하
    if (str.length <= 2) {
        var lastStr = str.slice(-1);
        while (str.length < 3) {
            str = str.concat(lastStr)
        }
    }
    
    return str;
}

문제 설명

S사에서는 각 부서에 필요한 물품을 지원해 주기 위해 부서별로 물품을 구매하는데 필요한 금액을 조사했습니다. 그러나, 전체 예산이 정해져 있기 때문에 모든 부서의 물품을 구매해 줄 수는 없습니다. 그래서 최대한 많은 부서의 물품을 구매해 줄 수 있도록 하려고 합니다.

물품을 구매해 줄 때는 각 부서가 신청한 금액만큼을 모두 지원해 줘야 합니다. 예를 들어 1,000원을 신청한 부서에는 정확히 1,000원을 지원해야 하며, 1,000원보다 적은 금액을 지원해 줄 수는 없습니다.

부서별로 신청한 금액이 들어있는 배열 d와 예산 budget이 매개변수로 주어질 때, 최대 몇 개의 부서에 물품을 지원할 수 있는지 return 하도록 solution 함수를 완성해주세요.

제한사항
  • d는 부서별로 신청한 금액이 들어있는 배열이며, 길이(전체 부서의 개수)는 1 이상 100 이하입니다.
  • d의 각 원소는 부서별로 신청한 금액을 나타내며, 부서별 신청 금액은 1 이상 100,000 이하의 자연수입니다.
  • budget은 예산을 나타내며, 1 이상 10,000,000 이하의 자연수입니다.

입출력 예

d budget result
[1,3,2,5,4] 9 3
[2,2,3,3] 10 4

나의 풀이

function solution(d, budget) {
    var answer = 0;
    
    // 최대한 많이 지원해줘야하니까 작은 지원금액부터 지원해주기
    d.sort(compare);
    //1, 2, 3, 4, 5
    for (let i=0; i<d.length; i++) {
        if (d[i] < budget) {
            answer += 1;
            budget -= d[i];
        } else if (d[i] == budget) {
            answer += 1;
            budget -= d[i];
            break;
        } else {
            continue;
        }
    }
 
    return answer
}

function compare(a, b) {
    return a-b
}

풀이 설명

최대한 많이 지원해줘야 하니까 d배열을 오름차순으로 정렬한 후, 앞에서부터 차례대로 지원해준다.
지원해주고 남은 예산이 그 다음 지원금액보다 작은지, 큰지, 같은지 비교한다.
1. d[2] > budget-d[1] 이면, d[3]이 지원가능한지 판단한다.
2. d[2] == budget-d[1] 이면, 해당 부서 지원을 끝으로 지원을 종료한다. 카운트 +1
3. d[2] < budget-d[1] 이면, 해당 부서를 지원해주고, 다음 부서로 넘어간다. 카운트 +1

+ Recent posts