🌠 문제

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.


지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.


"지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.


네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.

🌠 입력형식

  • 입력으로 지도의 한 변 크기 n 과 2개의 정수 배열 arr1, arr2가 들어온다.
  • 1 ≦ n ≦ 16
  • arr1, arr2는 길이 n인 정수 배열로 주어진다.
  • 정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n 이하이다. 즉, 0 ≦ x ≦ 2n - 1을 만족한다.

🌠 출력형식

  • 원래의 비밀지도를 해독하여 '#', 공백으로 구성된 문자열 배열로 출력하라.

🌠 입출력 예 설명

매개변수 값
n 5
arr1 [9, 20, 28, 18, 11]
arr2 [30, 1, 21, 17, 28]
출력 ["#####","# # #", "### #", "# ##", "#####"]


매개변수 값
n 6
arr1 [46, 33, 33 ,22, 31, 50]
arr2 [27 ,56, 19, 14, 14, 10]
출력 ["######", "### #", "## ##", " #### ", " #####", "### # "]


 

🧞 풀이

function solution(n, arr1, arr2) {
    let answer = [];
    let changedAnswer = [];
    
    arr1.forEach(el => {
        let temp = el.toString(2).split("").map(Number);
        while (temp.length !== n) {
            temp.unshift(0);
        }
        answer.push(temp);
    })
    
    arr2.forEach((el2, i) => {
        let temp2 = el2.toString(2).split("").map(Number);
        while (temp2.length !== n) {
            temp2.unshift(0);
        }
        temp2.forEach((e, j) => {
            if (e !== 0) {
                answer[i][j] = 1;
            }
        })
    })
    
    answer.forEach((row) => {
        changedAnswer.push(row.map((e) => e == 1 ? "#" : " ").join(""));
    })
    
    return changedAnswer;
}

💡 알게 된 점

  • toString(n)을 통해, 정수형을 n진법으로 변환할 수 있다.
  • unshift()를 통해, 배열 앞 자리에 큐 마냥 원하는 요소를 넣을 수 있다.
  • map()을 통해, 각 요소들을 조건에 맞게 쉽게 변형할 수 있다.

🌠 문제

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.

각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.
다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.

유저 ID 유저가 신고한 ID 설명
"muzi" "frodo" "muzi"가 "frodo"를 신고했습니다.
"apeach" "frodo" "apeach"가 "frodo"를 신고했습니다.
"frodo" "neo" "frodo"가 "neo"를 신고했습니다.
"muzi" "neo" "muzi"가 "neo"를 신고했습니다.
"apeach" "muzi" "apeach"가 "muzi"를 신고했습니다.
각 유저별로 신고당한 횟수는 다음과 같습니다.

유저 ID 신고당한 횟수
"muzi" 1
"frodo" 2
"apeach" 0
"neo" 2
위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.

유저 ID 유저가 신고한 ID 정지된 ID
"muzi" ["frodo", "neo"] ["frodo", "neo"]
"frodo" ["neo"] ["neo"]
"apeach" ["muzi", "frodo"] ["frodo"]
"neo" 없음 없음
따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.

이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.

🌠 제한사항

  • 2 ≤ id_list의 길이 ≤ 1,000
  • 1 ≤ id_list의 원소 길이 ≤ 10
  • id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
  • id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
  • 1 ≤ report의 길이 ≤ 200,000
  • 3 ≤ report의 원소 길이 ≤ 21
  • report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
  • 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
  • id는 알파벳 소문자로만 이루어져 있습니다.
  • 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
  • 자기 자신을 신고하는 경우는 없습니다.
  • 1 ≤ k ≤ 200, k는 자연수입니다.
  • return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.

🌠 입출력 예

id_list report k result
["muzi", "frodo", "apeach", "neo"] ["muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"] 2 [2,1,1,0]
["con", "ryan"] ["ryan con", "ryan con", "ryan con", "ryan con"] 3 [0,0]

🌠 입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

입출력 예 #2
"ryan"이 "con"을 4번 신고했으나, 주어진 조건에 따라 한 유저가 같은 유저를 여러 번 신고한 경우는 신고 횟수 1회로 처리합니다. 따라서 "con"은 1회 신고당했습니다. 3번 이상 신고당한 이용자는 없으며, "con"과 "ryan"은 결과 메일을 받지 않습니다. 따라서 [0, 0]을 return 합니다.


🧞 풀이

/*
[0, 1, 0, 1]
[0, 0, 0, 1]
[1, 1, 0, 0]
[0, 0, 0, 0]
*/

function solution(id_list, report, k) {
    let id_object = {}
    let counts = new Array(id_list.length).fill().map(() => new Array(id_list.length).fill(0));
    let reported = [];
    let answer = [];
    
    id_list.forEach((el, i) => {
        id_object[el] = i;
    })
    
    report.forEach((el) => {
        let temp = el.split(" ");
        if ( counts[id_object[temp[0]]][id_object[temp[1]]] == 0) {
            counts[id_object[temp[0]]][id_object[temp[1]]] += 1;            
        }
    })
    
    for (let i = 0; i < id_list.length; i++) {
        let temp_val = 0;
        for (let j = 0; j < id_list.length; j++) {
            temp_val += counts[j][i];
        }
        if (temp_val >= k) {
            reported.push(i);
        }
    }
    
    for (let k = 0; k < id_list.length; k++) {
        let temp_answer = 0;
        reported.forEach((e) => {
            if (counts[k][e] == 1) {
                temp_answer += 1;
            }
        })
        answer.push(temp_answer);
    }
    
    return answer;
}

💡 알게 된 점

  • 중복을 제거할 때, Set을 활용해서 중복을 제거한 것을 많이 확인할 수 있었다.
  • 본인은 0일 때라는 조건을 달아, 최초 신고만 접수할 수 있도록 했다.
  • reported 배열에 신고된 사람들의 인덱스를 담을 수 있게 했고,
  • answer 배열에 메일을 받을 사람들의 인덱스에 맞게 횟수를 담을 수 있도록 했다. 

🌠 문제

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

 



게임 화면은 "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

🌠 입출력 예 설명

인형의 처음 상태는 문제에 주어진 예시와 같습니다. 크레인이 [1, 5, 3, 5, 1, 2, 1, 4] 번 위치에서 차례대로 인형을 집어서 바구니에 옮겨 담은 후, 상태는 아래 그림과 같으며 바구니에 담는 과정에서 터트려져 사라진 인형은 4개 입니다.

 


🧞 풀이

function solution(board, moves) {
    let basket = [];
    let answer = 0;
    
    moves.forEach((el) => {
        for (let i = 0; i < board.length; i++) {
            if (board[i][el-1] != 0) {
                if (basket[basket.length-1] == board[i][el-1]) {
                    basket.pop();
                    console.log(basket);
                    console.log(board[i][el-1])
                    answer += 2;
                } else {
                    basket.push(board[i][el-1]);                    
                }
                board[i][el-1] = 0;
                break;
            }
        }
    })
    
    return answer;
}

💡 알게 된 점

  • JavaScript의 경우, 배열의 push와 pop을 활용하여, stack처럼 활용할 수 있다.
  • 항상 구현에는 조건을 잘 고민하고, console.log()를 통해 디버깅하자.

🌠 문제

선물을 직접 전하기 힘들 때 카카오톡 선물하기 기능을 이용해 축하 선물을 보낼 수 있습니다. 당신의 친구들이 이번 달까지 선물을 주고받은 기록을 바탕으로 다음 달에 누가 선물을 많이 받을지 예측하려고 합니다.

두 사람이 선물을 주고받은 기록이 있다면, 이번 달까지 두 사람 사이에 더 많은 선물을 준 사람이 다음 달에 선물을 하나 받습니다.
예를 들어 A가 B에게 선물을 5번 줬고, B가 A에게 선물을 3번 줬다면 다음 달엔 A가 B에게 선물을 하나 받습니다.
두 사람이 선물을 주고받은 기록이 하나도 없거나 주고받은 수가 같다면, 선물 지수가 더 큰 사람이 선물 지수가 더 작은 사람에게 선물을 하나 받습니다.
선물 지수는 이번 달까지 자신이 친구들에게 준 선물의 수에서 받은 선물의 수를 뺀 값입니다.
예를 들어 A가 친구들에게 준 선물이 3개고 받은 선물이 10개라면 A의 선물 지수는 -7입니다. B가 친구들에게 준 선물이 3개고 받은 선물이 2개라면 B의 선물 지수는 1입니다. 만약 A와 B가 선물을 주고받은 적이 없거나 정확히 같은 수로 선물을 주고받았다면, 다음 달엔 B가 A에게 선물을 하나 받습니다.
만약 두 사람의 선물 지수도 같다면 다음 달에 선물을 주고받지 않습니다.
위에서 설명한 규칙대로 다음 달에 선물을 주고받을 때, 당신은 선물을 가장 많이 받을 친구가 받을 선물의 수를 알고 싶습니다.

친구들의 이름을 담은 1차원 문자열 배열 friends 이번 달까지 친구들이 주고받은 선물 기록을 담은 1차원 문자열 배열 gifts가 매개변수로 주어집니다. 이때, 다음달에 가장 많은 선물을 받는 친구가 받을 선물의 수를 return 하도록 solution 함수를 완성해 주세요.

🌠 제한사항

  • 2 ≤ friends의 길이 = 친구들의 수 ≤ 50
  • friends의 원소는 친구의 이름을 의미하는 알파벳 소문자로 이루어진 길이가 10 이하인 문자열입니다.
  • 이름이 같은 친구는 없습니다.
  • 1 ≤ gifts의 길이 ≤ 10,000
  • gifts의 원소는 "A B"형태의 문자열입니다.
  • A는 선물을 준 친구의 이름을 B는 선물을 받은 친구의 이름을 의미하며 공백 하나로 구분됩니다.
  • A와 B는 friends의 원소이며 A와 B가 같은 이름인 경우는 존재하지 않습니다.

🌠 입출력 예

friends gifts result
["muzi", "ryan", "frodo", "neo"] ["muzi frodo", "muzi frodo", "ryan muzi", "ryan muzi", "ryan muzi", "frodo muzi", "frodo ryan", "neo muzi"] 2
["joy", "brad", "alessandro", "conan", "david"] ["alessandro brad", "alessandro joy", "alessandro conan", "david alessandro", "alessandro david"] 4
["a", "b", "c"] ["a b", "b a", "c a", "a c", "a c", "c a"] 0

 

🌠 입출력 예 설명

입출력 예 #1

주고받은 선물과 선물 지수를 표로 나타내면 다음과 같습니다.

↓준 사람 \ 받은 사람→ muzi ryan frodo neo
muzi - 0 2 0
ryan 3 - 0 0
frodo 1 1 - 0
neo 1 0 0 -
이름 준 선물 받은 선물 선물 지수
muzi 2 5 -3
ryan 3 1 2
frodo 2 2 0
neo 1 0 1
muzi는 선물을 더 많이 줬던 frodo에게서 선물을 하나 받습니다.
ryan은 선물을 더 많이 줬던 muzi에게서 선물을 하나 받고, 선물을 주고받지 않았던 neo보다 선물 지수가 커 선물을 하나 받습니다.
frodo는 선물을 더 많이 줬던 ryan에게 선물을 하나 받습니다.
neo는 선물을 더 많이 줬던 muzi에게서 선물을 하나 받고, 선물을 주고받지 않았던 frodo보다 선물 지수가 커 선물을 하나 받습니다.

다음달에 가장 선물을 많이 받는 사람은 ryan과 neo이고 2개의 선물을 받습니다. 따라서 2를 return 해야 합니다.

입출력 예 #2

주고받은 선물과 선물 지수를 표로 나타내면 다음과 같습니다.

↓준 사람 \ 받은 사람→ joy brad alessandro conan david
joy - 0 0 0 0
brad 0 - 0 0 0
alessandro 1 1 - 1 1
conan 0 0 0 - 0
david 0 0 1 0 -
이름 준 선물 받은 선물 선물 지수
joy 0 1 -1
brad 0 1 -1
alessandro 4 1 3
conan 0 1 -1
david 1 1 0
alessandro가 선물을 더 많이 줬던 joy, brad, conan에게서 선물을 3개 받습니다. 선물을 하나씩 주고받은 david보다 선물 지수가 커 선물을 하나 받습니다.
david는 선물을 주고받지 않았던 joy, brad, conan보다 선물 지수가 커 다음 달에 선물을 3개 받습니다.
joy, brad, conan은 선물을 받지 못합니다.

다음달에 가장 선물을 많이 받는 사람은 alessandro이고 4개의 선물을 받습니다. 따라서 4를 return 해야 합니다.

입출력 예 #3

a와 b, a와 c, b와 c 사이에 서로 선물을 주고받은 수도 같고 세 사람의 선물 지수도 0으로 같아 다음 달엔 아무도 선물을 받지 못합니다. 따라서 0을 return 해야 합니다.


🧞 풀이

function solution(friends, gifts) {
    // 이름 관련 인덱스
    let FI = {};
    // 선물 지수
    let GI = new Array(friends.length).fill(0);
    // 선물 교환 2차원 배열
    let PT = new Array(friends.length).fill().map(() => new Array(friends.length).fill(0));
    // 다음 달 선물 받는 사람
    let answer = new Array(friends.length).fill(0);
    
    // 친구들 인덱스 할당
    friends.forEach((el, i) => FI[el] = i);
    console.log(FI);

    for (let e of gifts) {
        let temp = e.split(" ");
        // 선물 지수 측정
        GI[FI[temp[0]]] += 1;
        GI[FI[temp[1]]] -= 1;
        
        // 선물 교환
        PT[FI[temp[0]]][FI[temp[1]]] += 1;
    }
    console.log(GI);
    console.log(PT);

    for (let i = 0; i < friends.length; i++) {
        for (let j = i + 1; j < friends.length; j++) {
            if (PT[i][j] !== 0 || PT[j][i] !== 0) {
                if (PT[i][j] !== PT[j][i]) {
                    if (PT[i][j] > PT[j][i]) {
                        answer[i] += 1;
                    } else {
                        answer[j] += 1;
                    }
                } else if (PT[i][j] === PT[j][i]) {
                    if (GI[i] > GI[j]) {
                        answer[i] += 1;
                    } else if (GI[j] > GI[i]) {
                        answer[j] += 1;
                    }
                }
            } else {
                if (GI[i] > GI[j]) {
                    answer[i] += 1;
                } else if (GI[j] > GI[i]) {
                    answer[j] += 1;
                }
            }
        }
    }
    
    console.log(answer);
    return Math.max(...answer);
}

💡 알게 된 점

  • new Array(길이).fill(0)을 통해, 길이만큼 0으로 가득찬 배열을 만들 수 있다.
  • new Array(길이.fill().map(() => new Array(길이).fill(0))을 통해 길이 x 길이만큼의 0으로 가득찬 2차원 배열을 만들 수 있다.
  • for of를 통해, 배열의 각 원소에 관한 반복문을 시행할 수 있다.
  • for in은 보통 객체의 각 원소를 반복할 때 사용한다.
  • 중복 탐색을 피하기 위해, 이중 반복문을 시행할 때, j의 경우, i + 1부터 시작하도록 한다.
  • Math.max() 함수 안에서는 ...answer과 같이, 구조 분해 할당하여, 배열 값들을 넣을 수 있도록 한다.
  • 구현은 어렵다... ㅜㅜ

 

🌠 문제

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

아이디의 길이는 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"

🌠 입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

입출력 예 #2
7단계를 거치는 동안 new_id가 변화하는 과정은 아래와 같습니다.

1단계 변화 없습니다.
2단계 "z-+.^." → "z-.."
3단계 "z-.." → "z-."
4단계 "z-." → "z-"
5단계 변화 없습니다.
6단계 변화 없습니다.
7단계 "z-" → "z--"

입출력 예 #3
7단계를 거치는 동안 new_id가 변화하는 과정은 아래와 같습니다.

1단계 변화 없습니다.
2단계 "=.=" → "."
3단계 변화 없습니다.
4단계 "." → "" (new_id가 빈 문자열이 되었습니다.)
5단계 "" → "a"
6단계 변화 없습니다.
7단계 "a" → "aaa"

입출력 예 #4
1단계에서 7단계까지 거치는 동안 new_id("123_.def")는 변하지 않습니다. 즉, new_id가 처음부터 카카오의 아이디 규칙에 맞습니다.

입출력 예 #5
1단계 변화 없습니다.
2단계 변화 없습니다.
3단계 변화 없습니다.
4단계 변화 없습니다.
5단계 변화 없습니다.
6단계 "abcdefghijklmn.p" → "abcdefghijklmn." → "abcdefghijklmn"
7단계 변화 없습니다.


🧞 풀이

function solution(new_id) {
    let filterList = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "-", "_", "."];
    
    let answer = new_id;
    
    // 1단계: 소문자 치환
    answer = answer.toLowerCase();
    
    // 2단계: 기타 문자 제거
    answer = answer.split("").filter((e) => filterList.includes(e)).join("");
    
    // 3단계: 하나의 마침표로 치환
    let result = [];
    for (let i = 0; i < answer.length; i++) {
        if (!(answer[i] === "." && result[result.length - 1] === ".")) {
            result.push(answer[i]);
        }
    }
    answer = result.join("");
    
    // 4단계: 처음, 끝의 마침표 제거
    if (answer.startsWith(".")) {
        answer = answer.slice(1);
    }
    if (answer.endsWith(".")) {
        answer = answer.slice(0, -1);
    }
    
    // 5단계: 빈 문자열일 경우, "a" 추가
    if (answer.length === 0) {
        answer = "a";
    }
    
    // 6단계: 문자 길이 제한 및 마지막 마침표 제거
    if (answer.length >= 16) {
        answer = answer.slice(0, 15);
        if (answer.endsWith(".")) {
            answer = answer.slice(0, -1);
        }
    }
    
    // 7단계. 문자 길이 3으로 제한
    while (answer.length < 3) {
        answer += answer[answer.length - 1];
    }
    
    return answer;
}

💡 알게 된 점

  • 정규표현식을 사용하면, 문제를 분명 쉽게 풀 수 있을 것이지만, 정규표현식이 기억이 나지 않아서, 만약 실전에서도 그런 경우가 생길 수 있기 때문에, 가지고 있는 역량으로 풀려고 노력했다.
  • Array.includes(): 배열에 특정 문자열의 존재 여부를 묻는 함수이다.
  • 대신, Array.indexOf()를 활용하여, -1이 아닌 경우를 찾는 경우도 있을 수 있다.
  • 자바스크립트는 파이썬과 달리 배열의 음수 인덱스 (array[-1])를 지원하지 않는다.
  • String.startsWith()와 String.endsWith()를 활용하여, 맨 앞과 끝의 문자가 무엇인지 확인할 수 있다.
  • 문자열을 자르는 것은 slice()와 substring()을 활용할 수 있을 것이다.
  • slice()는 음수 인덱스를 허용하지만, substring()은 허용하지 않는다.
  • 문자열에 문자열을 더하는 것은 '+' 연산자로 간단하게 가능하다.

🧩 정규표현식

function solution(new_id) {
    const answer = new_id
        .toLowerCase() // 1
        .replace(/[^\w-_.]/g, '') // 2
        .replace(/\.+/g, '.') // 3
        .replace(/^\.|\.$/g, '') // 4
        .replace(/^$/, 'a') // 5
        .slice(0, 15).replace(/\.$/, ''); // 6
    const len = answer.length;
    return len > 2 ? answer : answer + answer.charAt(len - 1).repeat(3 - len);
}

 

 

  • 문자와 숫자
    • 단일 문자나 숫자를 찾기 위해 사용됩니다.
    • 예: a, b, 1, 2
  • 메타문자
    • 특정 의미를 가진 특별한 문자들입니다.
    • .: 모든 단일 문자
    • ^: 문자열의 시작
    • $: 문자열의 끝
    • *: 0회 이상 반복
    • +: 1회 이상 반복
    • ?: 0회 또는 1회 반복
    • \: 이스케이프 문자로, 메타문자 자체를 찾고 싶을 때 사용
    • []: 문자 클래스. 대괄호 안에 있는 문자 중 하나와 일치
    • |: OR 연산자
    • (): 그룹화. 하위 표현식에 대해 캡처
  • 문자 클래스
    • [abc]: 'a', 'b', 'c' 중 하나
    • [^abc]: 'a', 'b', 'c'를 제외한 문자
    • [a-z]: 'a'부터 'z'까지의 모든 소문자
    • [A-Z]: 'A'부터 'Z'까지의 모든 대문자
    • [0-9]: 모든 숫자
  • 수량자
    • *: 0회 이상 반복
    • +: 1회 이상 반복
    • ?: 0회 또는 1회
    • {n}: 정확히 n회 반복
    • {n,}: n회 이상 반복
    • {n,m}: n회 이상 m회 이하 반복
  • 자주 사용하는 패턴
    • \d: 숫자 (0-9와 동일)
    • \D: 숫자가 아닌 것
    • \w: 단어 문자 (알파벳 + 숫자 + 밑줄)
    • \W: 단어 문자가 아닌 것
    • \s: 공백 문자 (스페이스, 탭 등)
    • \S: 공백 문자가 아닌 것

 

  • 기본 문자 찾기
    • cat: 'cat'과 일치
    • 123: '123'과 일치
  • 문자 클래스 사용
    • [abc]: 'a', 'b', 'c' 중 하나
    • [a-z]: 모든 소문자
    • [0-9]: 모든 숫자
  • 메타문자 사용
    • .: 임의의 한 문자 (개행 제외)
    • ^a: 'a'로 시작하는 문자열
    • z$: 'z'로 끝나는 문자열
  • 수량자 사용
    • a*: 'a'가 0회 이상 반복
    • a+: 'a'가 1회 이상 반복
    • a?: 'a'가 0회 또는 1회 존재
    • a{2}: 'a'가 정확히 2회 반복
    • a{2,}: 'a'가 2회 이상 반복
    • a{2,4}: 'a'가 2회 이상 4회 이하 반복
  • 복잡한 패턴
    • \d{3}-\d{2}-\d{4}: 형식 '123-45-6789'의 숫자
    • (abc|def): 'abc' 또는 'def'

 

 

🌠 문제

스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.

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

엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.
4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.
순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

🌠 제한사항

  • numbers 배열의 크기는 1 이상 1,000 이하입니다.
  • numbers 배열 원소의 값은 0 이상 9 이하인 정수입니다.
  • hand는 "left" 또는 "right" 입니다.
  • "left"는 왼손잡이, "right"는 오른손잡이를 의미합니다.
  • 왼손 엄지손가락을 사용한 경우는 L, 오른손 엄지손가락을 사용한 경우는 R을 순서대로 이어붙여 문자열 형태로 return 해주세요.

🌠 입출력 예

numbers hand result
[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] "right" "LRLLLRLLRRL"
[7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] "left" "LRLLRRLLLRR"
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0] "right" "LLRLLRLLRL"

🌠 입출력 예 설명

입출력 예 #1

순서대로 눌러야 할 번호가 [1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5]이고, 오른손잡이입니다.

왼손 위치 오른손 위치 눌러야 할 숫자 사용한 손 설명
* # 1 L 1은 왼손으로 누릅니다.
1 # 3 R 3은 오른손으로 누릅니다.
1 3 4 L 4는 왼손으로 누릅니다.
4 3 5 L 왼손 거리는 1, 오른손 거리는 2이므로 왼손으로 5를 누릅니다.
5 3 8 L 왼손 거리는 1, 오른손 거리는 3이므로 왼손으로 8을 누릅니다.
8 3 2 R 왼손 거리는 2, 오른손 거리는 1이므로 오른손으로 2를 누릅니다.
8 2 1 L 1은 왼손으로 누릅니다.
1 2 4 L 4는 왼손으로 누릅니다.
4 2 5 R 왼손 거리와 오른손 거리가 1로 같으므로, 오른손으로 5를 누릅니다.
4 5 9 R 9는 오른손으로 누릅니다.
4 9 5 L 왼손 거리는 1, 오른손 거리는 2이므로 왼손으로 5를 누릅니다.
5 9 - -
따라서 "LRLLLRLLRRL"를 return 합니다.

입출력 예 #2

왼손잡이가 [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2]를 순서대로 누르면 사용한 손은 "LRLLRRLLLRR"이 됩니다.

입출력 예 #3

오른손잡이가 [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]를 순서대로 누르면 사용한 손은 "LLRLLRLLRL"이 됩니다.


🧞 풀이

function solution(numbers, hand) {
    let keyPad = {1: ["L", 0, 0], 4: ["L", 1, 0], 7: ["L", 2, 0], 3: ["R", 0, 2], 6: ["R", 1, 2], 9: ["R", 2, 2]};
    let level = {2: [0, 1], 5: [1, 1], 8: [2, 1], 0: [3, 1]};

    let presentL = [3, 0];
    let presentR = [3, 2];

    let answer = [];

    numbers.forEach((e) => {
        if (keyPad[e] != undefined) {
            answer.push(keyPad[e][0]);
            if (keyPad[e][0] === "L") {
                presentL = [keyPad[e][1], keyPad[e][2]];
            } else {
                presentR = [keyPad[e][1], keyPad[e][2]];
            }
        } else {
            let target = level[e];
            let leftDistance = Math.abs(target[0] - presentL[0]) + Math.abs(target[1] - presentL[1]);
            let rightDistance = Math.abs(target[0] - presentR[0]) + Math.abs(target[1] - presentR[1]);
            let nearHand = leftDistance < rightDistance ? "L" : leftDistance > rightDistance ? "R" : hand === "right" ? "R" : "L";
            answer.push(nearHand);
            if (nearHand === "R") {
                presentR = target;
            } else {
                presentL = target;
            }
        }
    });

    return answer.join("");
}

💡 알게 된 점

  • [x1, y1] - [x2, y2]의 절댓값으로 2차원 배열의 요소 간 거리를 구할 수 있다.
  • 절댓값을 구하는 함수는 Math.abs(n)으로, Math 함수는 자바스크립트에 내장되어 있다.
  • 삼항연산자는 중첩 가능하다

🌠 문제

나만의 카카오 성격 유형 검사지를 만들려고 합니다.

성격 유형 검사는 다음과 같은 4개 지표로 성격 유형을 구분합니다. 성격은 각 지표에서 두 유형 중 하나로 결정됩니다.

 

지표 번호          성격 유형

1번 지표           라이언형(R), 튜브형(T)

2번 지표           콘형(C), 프로도형(F)

3번 지표           제이지형(J), 무지형(M)

4번 지표           어피치형(A), 네오형(N)

4개의 지표가 있으므로 성격 유형은 총 16(=2 x 2 x 2 x 2)가지가 나올 수 있습니다. 예를 들어, "RFMN"이나 "TCMA"와 같은 성격 유형이 있습니다.

 

검사지에는 총 n개의 질문이 있고, 각 질문에는 아래와 같은 7개의 선택지가 있습니다.

 

매우 비동의

비동의

약간 비동의

모르겠음

약간 동의

동의

매우 동의

각 질문은 1가지 지표로 성격 유형 점수를 판단합니다.

 

예를 들어, 어떤 한 질문에서 4번 지표로 아래 표처럼 점수를 매길 수 있습니다.

 

선택지   성격 유형 점수

매우 비동의       네오형 3

비동의   네오형 2

약간 비동의       네오형 1

모르겠음           어떤 성격 유형도 점수를 얻지 않습니다

약간 동의          어피치형 1

동의      어피치형 2

매우 동의          어피치형 3

이때 검사자가 질문에서 약간 동의 선택지를 선택할 경우 어피치형(A) 성격 유형 1점을 받게 됩니다. 만약 검사자가 매우 비동의 선택지를 선택할 경우 네오형(N) 성격 유형 3점을 받게 됩니다.

 

위 예시처럼 네오형이 비동의, 어피치형이 동의인 경우만 주어지지 않고, 질문에 따라 네오형이 동의, 어피치형이 비동의인 경우도 주어질 수 있습니다.

하지만 각 선택지는 고정적인 크기의 점수를 가지고 있습니다.

 

매우 동의나 매우 비동의 선택지를 선택하면 3점을 얻습니다.

동의나 비동의 선택지를 선택하면 2점을 얻습니다.

약간 동의나 약간 비동의 선택지를 선택하면 1점을 얻습니다.

모르겠음 선택지를 선택하면 점수를 얻지 않습니다.

검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은 점수를 받은 성격 유형이 검사자의 성격 유형이라고 판단합니다. , 하나의 지표에서 각 성격 유형 점수가 같으면, 두 성격 유형 중 사전 순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단합니다.

 

질문마다 판단하는 지표를 담은 1차원 문자열 배열 survey와 검사자가 각 질문마다 선택한 선택지를 담은 1차원 정수 배열 choices가 매개변수로 주어집니다. 이때, 검사자의 성격 유형 검사 결과를 지표 번호 순서대로 return 하도록 solution 함수를 완성해주세요.

🌠 제한사항

1 ≤ survey의 길이 ( = n) ≤ 1,000

survey의 원소는 "RT", "TR", "FC", "CF", "MJ", "JM", "AN", "NA" 중 하나입니다.

survey[i]의 첫 번째 캐릭터는 i+1번 질문의 비동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.

survey[i]의 두 번째 캐릭터는 i+1번 질문의 동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.

choices의 길이 = survey의 길이

 

choices[i]는 검사자가 선택한 i+1번째 질문의 선택지를 의미합니다.

1 ≤ choices의 원소 ≤ 7

choices 

1          매우 비동의

2          비동의

3          약간 비동의

4          모르겠음

5          약간 동의

6          동의

7          매우 동의

🌠 입출력 예

survey   choices  result

["AN", "CF", "MJ", "RT", "NA"]        [5, 3, 2, 7, 5]       "TCMA"

["TR", "RT", "TR"] [7, 1, 3]  "RCJA"

🌠 입출력 예 설명

입출력 예 #2

 

1번부터 3번까지 질문의 성격 유형 점수를 합치면 아래 표와 같습니다.

 

지표 번호          성격 유형          점수     성격 유형          점수

1번 지표           라이언형(R)        6          튜브형(T)           1

2번 지표           콘형(C)  0          프로도형(F)        0

3번 지표           제이지형(J)        0          무지형(M)          0

4번 지표           어피치형(A)        0          네오형(N)          0

1번 지표는 튜브형(T)보다 라이언형(R)의 점수가 더 높습니다. 따라서 첫 번째 지표의 성격 유형은 R입니다.

하지만, 2, 3, 4번 지표는 모두 0점으로 동일한 점수입니다. 따라서 2, 3, 4번 지표의 성격 유형은 사전순으로 빠른 C, J, A입니다.

 

따라서 "RCJA" return 해야 합니다.


🧞 풀이

function solution(survey, choices) {
    let total_points = {"R": 0, "T": 0, "C": 0, "F": 0, "J": 0, "M": 0, "A": 0, "N": 0};
    let answer = [];
    
    survey.forEach((e, i) => {
        let disagree_temp = e[0];
        let agree_temp = e[1];
        
        if (choices[i] > 4) {
            total_points[agree_temp] += choices[i] - 4;
        } else if (choices[i] < 4) {
            total_points[disagree_temp] += 4 - choices[i];
        }
    })
     
    if (total_points["R"] < total_points["T"]) {
        answer.push("T");
    } else {
        answer.push("R");
    }
    
    if (total_points["C"] < total_points["F"]) {
        answer.push("F");
    } else {
        answer.push("C");
    }
    
    if (total_points["J"] < total_points["M"]) {
        answer.push("M");
    } else {
        answer.push("J");
    }
    
    if (total_points["A"] < total_points["N"]) {
        answer.push("N");
    } else {
        answer.push("A");
    }
    
    return answer.join("");
}

💡 알게 된 점

  • forEach()에서 index를 적극 활용하면, index까지 꺼내서 활용할 수 있다.
  • 처음에는 if문을 4개 사용하지 않고, for문을 통해, object의 key 값을 꺼내 array로 만들어, 반복을 하려 했으나, 때로는 단순한게 더 직관적인 것 같아, 다음과 같이 풀었다.

🌠 문제

슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.

이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.


실패율은 다음과 같이 정의한다.
스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.

🌠 제한사항

  • 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
  • stages의 길이는 1 이상 200,000 이하이다.
  • stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
  • 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
  • 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
  • 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
  • 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.

🌠 입출력 예

N Stages Result
5 [2, 1, 2, 6, 2, 4, 3, 3] [3, 4, 2, 1, 5]
4 [4, 4, 4, 4, 4] [4, 1, 2, 3]

 

🌠 입출력 예 설명

입출력 예 #1
1번 스테이지에는 총 8명의 사용자가 도전했으며, 이 중 1명의 사용자가 아직 클리어하지 못했다. 따라서 1번 스테이지의 실패율은 다음과 같다.
1 번 스테이지 실패율 : 1/8
2번 스테이지에는 총 7명의 사용자가 도전했으며, 이 중 3명의 사용자가 아직 클리어하지 못했다. 따라서 2번 스테이지의 실패율은 다음과 같다.
2 번 스테이지 실패율 : 3/7
마찬가지로 나머지 스테이지의 실패율은 다음과 같다.
3 번 스테이지 실패율 : 2/4
4번 스테이지 실패율 : 1/2
5번 스테이지 실패율 : 0/1
각 스테이지의 번호를 실패율의 내림차순으로 정렬하면 다음과 같다.
[3,4,2,1,5]


입출력 예 #2
모든 사용자가 마지막 스테이지에 있으므로 4번 스테이지의 실패율은 1이며 나머지 스테이지의 실패율은 0이다.
[4,1,2,3]


🧞 풀이

function solution(N, stages) {
    let answer = {};
    for (let i = 1; i <= N; i++) {
        let deno = stages.filter((e) => e === i).length; 
        let nume = stages.filter((e) => e >= i).length; 
        if (nume === 0) {
            answer[i] = 0;
        } else {
            answer[i] = deno / nume;
        }
    }

    let sortedArray = Object.keys(answer);

    sortedArray.sort((a, b) => answer[b] - answer[a] || a - b);

    return sortedArray.map(item => parseInt(item));
}

💡 알게 된 점

  • Object.keys(obj)를 통해 객체의 키만 담은 배열을 반환할 수 있다.
    • 자매품으로 Object.values(obj)는 객체의 값만, Object.entries(obj)는 [키, 값] 쌍을 담은 배열을 반환한다.
  • answer[b] - answer[a]는 내림차순 정렬을 위한 비교식인데, 해당 값이 0이 되면, 이는 false를 뜻하게 된다.
  • 따라서 논리 연산자 ||에서 거짓으로 넘어가, 그 다음 식인 a - b를 비교하게 되는데, 이를 통해 실패율에 따른 내림차순 정렬과, 실패율이 같을 때는 오름차순 정렬을 유지할 수 있게 된다.
  • 그렇지만 이미 오름차순 정렬로 되어 있기 때문에, 해당 부분은 불필요하다고 할 수 있긴 하다.
  • parseInt() 함수나 Number()함수를 통해, 문자열을 숫자, 혹은 정수형으로 형변환할 수 있다.

+ Recent posts