programmers.co.kr/learn/courses/30/lessons/17679

 

코딩테스트 연습 - [1차] 프렌즈4블록

프렌즈4블록 블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 프렌즈4블록. 같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙

programmers.co.kr

<풀이>

1. 주어진 보드에서 지워질 4개의 블록을 모두 지운다.

2. 지워진 블록 위에있는 블록들을 아래로 내린다.

3. 더 이상 블록을 지울 수 없을 때 까지 반복한다.

4. 지워진 블록 개수를 반환한다

 

<해법>

문제를 푸는데 특별한 아이디어가 필요하지 않습니다. 문제에서 주어진 대로 정확하게 구현하는게 핵심입니다.

 

① 주어진 보드에서 지워질 4개의 블록들을 모두 찾는다.

: 바로 지우면 안됩니다. 블록을 중복해서 찾아야하기 때문입니다. 저는 지워질 4개의 블록들의 좌표를 모아놓고, 그 좌표의 블록들을 지우는 방식으로 구현하였습니다.

 

② 지워질 블록들을 지운다.

 

③ 블록들을 내린다.

: 빈 칸위에 블록이 있으면 안됩니다. 저는 빈 칸위에 블록이 있는 경우, 위에 있는 가장 가까운 블록으로 해당 빈칸을 채우는 방식으로 구현하였습니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
//구조체 : 좌표
struct pos {
    int x, y;
};
 
int M, N;
vector<string> map;
 
//x, y좌표에서 지울 수 있는 4블록인지 확인
bool is_4Block(int x, int y, char c) {
 
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            if (map[x + i][y + j] != c) {
                return false;
            }
        }
    }
    return true;
}
 
//블록 내리기
void blockDown() {
 
    for (int i = M - 1; i >= 0; i--) {
        for (int j = 0; j < N; j++) {
 
            //빈 칸 탐색
            if (map[i][j] == '#') {
 
                //빈 칸위에 블록이 있는지 탐색
                for (int k = i; k >= 0; k--) {
 
                    //빈 칸 위에 있는 가장 가까운 블록하나 내리기
                    if (map[k][j] != '#') {
                        map[i][j] = map[k][j];
                        map[k][j] = '#';
                        break;
                    }
                }
            }
        }
    }
}
 
//지워진 블록 세기
int countRemoveBlock() {
 
    int count = 0;
 
    //빈 칸 개수 세기
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            if (map[i][j] == '#') {
                count++;
            }
        }
    }
 
    return count;
}
 
int solution(int m, int n, vector<string> board) {
 
    int answer = 0;
 
    //초기화(전역 변수로 사용하기 위해)
    M = m, N = n;
    map = board;
 
    //해법
    while (true) {
 
        //지울 블록의 좌표를 담는 벡터
        vector<pos> removeBlock;
 
        //지울 블록 정하기
        for (int i = 0; i < M - 1; i++) {
            for (int j = 0; j < N - 1; j++) {
 
                //빈 칸이 아니고, 4블록을 지울 수 있는 경우
                if (map[i][j] != '#' && is_4Block(i, j, map[i][j])) {
                    
                    //지울 블록 4개의 좌표를 벡터에 담는다
                    removeBlock.push_back({ i, j });
                    removeBlock.push_back({ i, j + 1 });
                    removeBlock.push_back({ i + 1, j });
                    removeBlock.push_back({ i + 1, j + 1 });
                }
            }
        }
 
        //종료 조건 : 지울 블록이 없는 경우
        if (removeBlock.empty()) {
            break;
        }
 
        //블록 지우기
        for (int i = 0; i < removeBlock.size(); i++) {
            int x = removeBlock[i].x;
            int y = removeBlock[i].y;
 
            map[x][y] = '#';
        }
 
        //블록 내리기
        blockDown();
    }
 
    //결과 계산
    answer = countRemoveBlock();
 
    //결과 반환
    return answer;
}
 
 

 

구현에 대해 알아볼 수 있는 문제였습니다.

programmers.co.kr/learn/courses/30/lessons/17678

 

코딩테스트 연습 - [1차] 셔틀버스

10 60 45 [23:59,23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59, 23:59] 18:00

programmers.co.kr

<풀이>

1. 셔틀버스 정보와 크루들의 정보를 입력받는다.

2. 셔틀버스를 타고 갈 수 있는 가장 늦은 시간을 반환한다.

 

<해법>

이 문제는 특별한 아이디어를 통해 푸는 문제가 아니라고 생각합니다. 시뮬레이션을 구현하고, 그에 따라 답을 구하는 방식의 문제라고 생각합니다. 저는 아래 그림과 같은 방법으로 시뮬레이션을 구현하였고 답을 구하였습니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
 
using namespace std;
 
priority_queue<int, vector<int>, greater<int>> timetable_int;
queue<int> line;
 
//문자열 시간 -> int 시간으로 바꾸기
int toIntTime(string time) {
 
    int res = 0;
 
    int hour = stoi(time.substr(02)) * 60;
    int minute = stoi(time.substr(32));
 
    res = hour + minute;
 
    return res;
}
 
//int 시간 -> 문자열 시간으로 바꾸기
string toStringTime(int time) {
 
    string res = "";
 
    string hour = to_string(time / 60);
    if (hour.length() < 2) {
        hour = "0" + hour;
    }
 
    string minute = to_string(time % 60);
    if (minute.length() < 2) {
        minute = "0" + minute;
    }
 
    res = hour + ":" + minute;
 
    return res;
}
 
string solution(int n, int t, int m, vector<string> timetable) {
 
    string answer = "";
 
    //정답으로 바꿀 int형 시간
    int answerTime_int = 0;
 
    //문자열 시간을 int형 시간으로 바꾼 후, 우선순위 큐에 저장
    for (int i = 0; i < timetable.size(); i++) {
 
        int time = toIntTime(timetable[i]);
 
        timetable_int.push(time);
    }
    
    //셔틀 버스 반복 수행
    for (int i = 0; i < n; i++) {
 
        //버스 오는 시간
        int busTime = 540 + i * t;
 
        //버스 오는 시간 전까지 도착한 사람 줄 세우기
        while (true) {
            if (timetable_int.empty() || timetable_int.top() > busTime) {
                break;
            }
            line.push(timetable_int.top());
            timetable_int.pop();
        }
 
        /*
        줄 서 있는 사람 수 < 버스에 태울 수 있는 사람 수 일 경우,
        버스가 오는 시간에 맞춰 도착하면 된다.
        */
        if (line.size() < m) {
            answerTime_int = busTime;
            for (int j = 0; j < line.size(); j++) {
                line.pop();
            }
        }
        /*
        줄 서 있는 사람 >= 버스에 태울 수 있는 사람 수 일 경우,
        버스에 탈 수 있는 마지막 사람보다 1분 일찍오면 된다.
        */
        else {
            for (int j = 0; j < m - 1; j++) {
                line.pop();
            }
            answerTime_int = line.front() - 1;
            line.pop();
        }
    }
 
    //결과
    answer = toStringTime(answerTime_int);
 
    //결과 반환
    return answer;
}
 

 

시뮬레이션에 대해 알아볼 수 있는 문제였습니다.

programmers.co.kr/learn/courses/30/lessons/17677

 

코딩테스트 연습 - [1차] 뉴스 클러스터링

뉴스 클러스터링 여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브

programmers.co.kr

<풀이>

1. 주어진 두 개의 문자열을 두 글자씩 끊어서 다중집합으로 만듭니다.

2. 두 집합의 교집합, 합집합 원소의 개수를 구한 후 자카드 유사도를 계산합니다.

3. 자카드 유사도를 반환합니다.

 

<해법>

1. 두 개의 다중집합의 교집합 원소 개수를 구하는 방법

=> 저는 아래 그림과 같은 방법으로 진행하였습니다. 모든 원소를 비교하면서, 비교해서 같은 원소는 다시 비교되지 않도록 맵핑을 하였습니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
 
using namespace std;
 
//문자 판단 함수
bool isChar(char c) {
    if (c >= 'a' && c <= 'z') {
        return true;
    }
    return false;
}
 
int solution(string str1, string str2) {
    int answer = 0;
 
    //2글자씩 끊어서 저장할 벡터
    vector<string> v1, v2;
 
    //교집합 개수, 합집합 개수 변수
    int bunja = 0;
    int bunmo = 0;
 
    //대문자 -> 소문자 변환
    for (int i = 0; i < str1.length(); i++) {
        str1[i] = tolower(str1[i]);
    }
    for (int i = 0; i < str2.length(); i++) {
        str2[i] = tolower(str2[i]);
    }
 
    //문자열에서 문자만 2글자씩 잘라 벡터에 저장
    for (int i = 0; i < str1.length() - 1; i++) {
        if(isChar(str1[i]) && isChar(str1[i + 1])) {
            v1.push_back(str1.substr(i, 2));
        }
    }
    for (int i = 0; i < str2.length() - 1; i++) {
        if (isChar(str2[i]) && isChar(str2[i + 1])) {
            v2.push_back(str2.substr(i, 2));
        }
    }
 
    //교집합 개수 찾기
    for (int i = 0; i < v1.size(); i++) {
        for (int j = 0; j < v2.size(); j++) {
            
            //같은 원소가 있다면, 교집합 개수 + 1
            if (v1[i] == v2[j]) {
 
                bunja++;
                
                //해당 원소를 다시 셀 수 없도록 맵핑
                v2[j] = "#";
 
                break;
            }
        }
    }
 
    //결과 계산
    bunmo = v1.size() + v2.size() - bunja;
 
    if (bunmo == 0) {
        answer = 65536;
    }
    else {
        answer = bunja * 65536 / bunmo;
    }
 
    //결과 반환
    return answer;
}
 

 

구현에 대해 알아볼 수 있는 문제였습니다.

programmers.co.kr/learn/courses/30/lessons/17676

 

코딩테스트 연습 - [1차] 추석 트래픽

입력: [ 2016-09-15 20:59:57.421 0.351s, 2016-09-15 20:59:58.233 1.181s, 2016-09-15 20:59:58.299 0.8s, 2016-09-15 20:59:58.688 1.041s, 2016-09-15 20:59:59.591 1.412s, 2016-09-15 21:00:00.464 1.466s, 2016-09-15 21:00:00.741 1.581s, 2016-09-15 21:00:00.748

programmers.co.kr

<풀이>

1. 주어진 문자열을 통해 '요청 시작 시간'과 '처리 완료 시간'을 분리합니다.

2. 초당 최대 처리량을 결과값으로 저장합니다.

3. 결과를 반환합니다.

 

<해법>

1. 문자열 문제 마음가짐

=> 문자열 문제를 마주했을 때, 가장 먼저 '문자열을 다루는 함수'를 적극적으로 사용하겠다는 마음가짐을 가져야합니다. 저는 문자열 문제를 풀 때, 간단한 조건식으로 풀 수 있는 문제라도 문자열을 다루는 함수를 적극적으로 사용하여 문제를 풉니다.

 

2. 시간 계산

=> 초당 최대 처리량을 구하기 위해서는 각 문자열 마다 '요청 시작 시간'을 알아야합니다. 또, '요청 시작 시간'을 구하기 위해서는 시간을 계산할 수 있는 형태로 만들어야 합니다. 그래서, 저는 시간을 millisecond형태로 바꾸어서 계산하였습니다.

 

3. 초당 최대 처리량을 구하는 방법

=> 시간은 '응답 완료 시간'을 기준으로 오름차순 되어있습니다. 각 시간의 '응답 완료 시간'부터 1초 후 시간까지 선을 그어가며 초당 처리량을 구합니다. 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
//구조 : 시간(시작 시간, 끝 시간)
struct Time {
    int start_time, end_time;
};
 
int solution(vector<string> lines) {
 
    int answer = 0;
 
    vector<Time> v;
 
    //문자열 파싱
    for (int i = 0; i < lines.size(); i++) {
        string h, m, s, process;
        int int_h, int_m, int_s, int_process;
 
        //시, 분, 초, 처리시간 파싱 (ex. "2016-09-15 20:59:57.421 0.351s")
        h = lines[i].substr(112); //"20"
        m = lines[i].substr(142); //"59"
        s = lines[i].substr(176); //"57.421"
        process = lines[i].substr(24); //"0.351s"
        process = process.substr(0, process.length() - 1); //"0.351"
 
        //string -> int
        int_h = stoi(h) * 60 * 60 * 1000;
        int_m = stoi(m) * 60 * 1000;
        int_s = stod(s) * 1000;
        int_process = stod(process) * 1000;
 
        //시간 변수(시작시간, 끝시간) 생성 
        int end_time = int_h + int_m + int_s;
        int start_time = end_time - int_process + 1;
        Time t = { start_time, end_time };
 
        //저장
        v.push_back(t);
    }
 
    //초당 최대 처리량 구하기
    for (int i = 0; i < v.size(); i++) {
 
        int tmpAnswer = 0;
 
        Time t = v[i];
        int check_time = t.end_time + 1000 - 1;
 
        //끝 시간 보다 시작 시간이 작다면, 처리량 + 1
        for (int j = i; j < v.size(); j++) {
            if (v[j].start_time <= check_time) {
                tmpAnswer++;
            }
        }
 
        //최대 처리량 갱신
        if (tmpAnswer > answer) {
            answer = tmpAnswer;
        }
    }
 
    return answer;
}
 

 

문자열 처리에 대해 알아볼 수 있는 문제였습니다.

https://programmers.co.kr/learn/courses/30/lessons/42890

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

<풀이>

1. 가능한 모든 후보키를 계산합니다.

2. 유일성과 최소성을 확인하여 가능한 후보키만을 결과값으로 저장합니다.

3. 결과를 출력합니다.

 

<해법>

1. 가능한 모든 후보키를 계산하는 방법.

=> 모든 경우의 수를 계산하는 대표적인 방법으로 '백트래킹'이 있습니다. 저는 '백트래킹'을 재귀함수를 이용하여 구현하였고, 저는 구현하기 이전에 아래와 같은 그림으로 큰 틀을  잡습니다.

 

2. 유일성 확인하는 방법

=> 해당하는 속성의 값을 한 문자열로 만들고 정렬을 해준 후, 같은 문자가 있는지 확인하였습니다. 같은 문자가 있을 경우 유일성 조건에서 탈락하는 방식으로 진행하였습니다.

 

3. 최소성 확인하는 방법

=> 확인해야 할 후보키를 정답이 가능한 후보키들과 비교하였습니다. 정답이 가능한 후보키에 부분집합만 되지 않으면 가능하므로, 다른 속성이 한가지라도 있는지 확인하고 한가지라도 있으면 최소성 조건에 부합하는 방식으로 진행하였습니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
 
int col, row;
vector<vector<string>> r;
vector<int> v;
vector<vector<int>> key;
 
void go(int index, int cnt) {
 
    //원하는 개수를 다 뽑았으면
    if (cnt == 0) {
        
        //최소성 확인 - 후보키에 이미 같은 조합이 있는지 확인
        if (!key.empty()) {
            for (int i = 0; i < key.size(); i++) {
 
                bool isMinimal = false;
 
                //후보키 안에 모두 같은 속성이 있을 시 minimal X
                //-> 후보키 안에 하나라도 다른 속성이 있으면 OK
                for (int j = 0; j < key[i].size(); j++) {
                    bool alreadyIn = false;
                    for (int k = 0; k < v.size(); k++) {
                        if (key[i][j] == v[k]) {
                            alreadyIn = true;
                        }
                    }
                    if (!alreadyIn) {
                        isMinimal = true;
                    }
                }
                
                if (!isMinimal) {
                    return;
                }
            }
        }
        
        //유일성 확인 - 모든 튜플을 식별할 수 있는지 확인
        vector<string> cmp;
        bool isUnique = true;
 
        //후보키로 문자열 만들기
        for (int i = 0; i < row; i++) {
            string s = "";
            for (int j = 0; j < v.size(); j++) {
                s += r[i][v[j]];
            }
            cmp.push_back(s);
        }
 
        sort(cmp.begin(), cmp.end());
        
        //문자열 중 같은 것이 있다면 -> 식별X
        for (int i = 0; i < row - 1; i++) {
            if (cmp[i] == cmp[i + 1]) {
                isUnique = false;
            }
        }
 
        //최종적으로 가능한 후보키 저장
        if (isUnique) {
            key.push_back(v);
        }
 
        return;
    }
 
    //갯수만큼 저장
    for (int i = index; i < col; i++) {
        v.push_back(i);
        go(i + 1, cnt - 1);
        v.pop_back();
    }
 
    return;
}
 
int solution(vector<vector<string>> relation) {
    int answer = 0;
 
    //전역변수에 값 저장
    r = relation;
    col = relation[0].size();
    row = relation.size();
 
    //1,2.. 개씩 뽑기
    for (int i = 1; i <= col; i++) {
        go(0, i);
    }
 
    //결과 저장
    answer = key.size();
 
    return answer;
}
 

 

백트래킹에 대해 알아볼 수 있는 문제였습니다.

https://programmers.co.kr/learn/courses/30/lessons/42889

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

<풀이>

1. 주어진 입력으로 실패율을 구하는데 필요한 분모와 분자를 구한다.

2. 스테이지의 번호와 실패율을 벡터에 저장한다.

3. 주어진 조건에 따라 벡터를 정렬한다.

4. 결과를 저장한다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
 
bool cmp(pair<int,double> a, pair<int,double> b) {
 
    //실패율이 같을 경우, 스테이지 번호가 낮은 순으로 정렬
    if (a.second == b.second) {
        return a.first < b.first;
    }
    else {
        return a.second > b.second;
    }
}
 
vector<int> solution(int N, vector<int> stages) {
    vector<int> answer;
 
    int bunJa[502];
    int bunMo[502];
    memset(bunJa, 0sizeof(bunJa));
    memset(bunMo, 0sizeof(bunMo));
 
    //vector<스테이지 번호, 실패율>
    vector<pair<int,double>> rate;
 
    //각각 스테이지 실패율의 분모, 분자 구하기
    for (int i = 0; i < stages.size(); i++) {
        for (int j = 1; j <= stages[i]; j++) {
            bunMo[j]++;
        }
        bunJa[stages[i]]++;
    }
 
    //실패율 구하기
    for (int i = 1; i <= N; i++) {
        if (bunMo[i] == 0) {
            rate.push_back({ i,0 });
        }
        else {
            rate.push_back({ i,double(bunJa[i]) / double(bunMo[i]) });
        }
    }
 
    //실패율 정렬 
    sort(rate.begin(), rate.end(), cmp);
 
    //결과 저장
    for (int i = 0; i < N; i++) {
        answer.push_back(rate[i].first);
    }
 
    return answer;
}
 

 

구현에 대해 알아볼 수 있는 문제였습니다.

https://programmers.co.kr/learn/courses/30/lessons/64064

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

<풀이>

1. 제재 아이디가 가능한 모든 경우를 계산한다.

2. 중복되는 제재 아이디 경우를 제외합니다.

3. 모든 경우의 수를 출력합니다.

 

<해법>

1. 제재 아이디가 가능한 모든 경우를 계산하는 방법.

=> 모든 경우를 시뮬레이션 하는 대표적인 방법으로 '백트래킹'이 있습니다. 위 문제에서 저는 '백트래킹'을 재귀함수로 구현하였습니다. 저는 재귀함수로 구현하기 이전에 아래와 같은 그림으로 대표적인 틀을 잡습니다.

 

2. 중복되는 경우를 제외하는 방법.

=> 위 문제에서 중복되는 경우는 두 가지가 있습니다. 아이디가 중복되서는 안되며, 나열된 아이디 내용들이 중복되서는 안됩니다. 

(1) 아이디 중복 제외

저는 방문 배열을 이용하여 이전 단계에서 제재 아이디로 탐색된 경우, 탐색을 할 수 없도록 하였습니다.

(2) 나열된 아이디 내용들 중복 제외

저는 자료구조 'set'를 사용하였습니다. 'set'를 이용하여 중복된 내용이 담겼을 경우 제외되도록 하였습니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <string>
#include <vector>
#include <set>
using namespace std;
 
vector<string> user;
vector<string> banned;
bool visited[10];
set<string> s;
 
void go(int index) {
 
    //종료조건 : 모든 불량 사용자 아이디 탐색 완료
    if (index == banned.size()) {
 
        //제재 아이디로 등록된 아이디 한 문자열로 만들기
        string tmp = "";
        for (int i = 0; i < user.size(); i++) {
            if (visited[i]) {
                tmp += user[i];
            }
        }
 
        //세트로 중복 제거
        s.insert(tmp);
        return;
    }
 
    //불량 사용자 아이디 마다 가능한 제재 아이디 탐색
    for (int i = 0; i < user.size(); i++) {
 
        bool isAble = true;
        
        //이전 탐색에서 제재 아이디로 등록된 경우 -> 불가능
        if (visited[i]) {
            continue;
        }
 
        //아이디 길이가 다를 경우 -> 불가능
        if (user[i].length() != banned[index].length()) {
            continue;
        }
 
        //각 문자 비교 탐색
        for (int j = 0; j < user[i].length(); j++) {
            if (banned[index][j] == '*') {
                continue;
            }
            //문자가 다를경우 -> 불가능
            if (banned[index][j] != user[i][j]) {
                isAble = false;
                break;
            }
        }
 
        //제재 아이디가 가능한 경우 -> 다음 단계
        if (isAble) {
            visited[i] = true;
            go(index + 1);
            visited[i] = false;
        }
    }
    return;
}
 
int solution(vector<string> user_id, vector<string> banned_id) {
    int answer = 0;
 
    user = user_id;
    banned = banned_id;
 
    //재귀함수 시작
    go(0);
 
    //결과 저장
    answer = s.size();
 
    return answer;
}
 

 

백트래킹에 대해 알아볼 수 있는 문제였습니다.

https://programmers.co.kr/learn/courses/30/lessons/42888

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

<풀이>

1. 주어진 명령(문자열)을 해독하여 각각 유저 아이디와 닉네임을 매칭한다.

2. 명령에 맞는 출력물을 결과에 저장한다.

<해법>

1. 문자열을 해독하는 방법.

=> 각 문자열은 공백으로 구분되어 있다고 합니다. 그렇다면, 문자열에서 공백까지 문자는 각각의 정보를 담고있다고 해석할 수 있습니다.

예를들어 "Enter uid1234 Muzi"의 문자열을 탐색할 때, 앞에서부터 공백이 나오기 전까지 한 문자씩 검사합니다.

E -> n -> t -> e -> r -> ' ' // 공백 발견

공백을 발견하였을 시 그 전까지 문자들 Enter을 저장합니다.

위와 같은 수행을 반복하면 Enter, uid1234, Muzi를 나눌 수 있습니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
 
struct message {
    string cmd;
    string user_id;
};
 
vector<string> solution(vector<string> record) {
 
    vector<string> answer;
 
    map<stringstring> user;
    vector<message> v;
 
    for (int i = 0; i < record.size(); i++) {
 
        //문자열 분리
        //tmpV[0] : Enter or Leave or tmpV, tmpV[1] : uidXXXX, tmpV[2] : nickname
        vector<string> tmpV;
        string tmp = "";
        for (int j = 0; j < record[i].length(); j++) {
            if (record[i][j] == ' ') {
                tmpV.push_back(tmp);
                tmp = "";
            }
            else {
                tmp += record[i][j];
            }
        }
        tmpV.push_back(tmp);
 
        //명령 수행
        if (tmpV[0== "Enter") {
            user[tmpV[1]] = tmpV[2];
            v.push_back({ "Enter",tmpV[1] });
        }
        else if (tmpV[0== "Leave") {
            v.push_back({ "Leave", tmpV[1] });
        }
        else {
            user[tmpV[1]] = tmpV[2];
        }
    }
 
    //결과값 저장
    for (int i = 0; i < v.size(); i++) {
        if (v[i].cmd == "Enter") {
            answer.push_back(user[v[i].user_id] + "님이 들어왔습니다.");
        }
        else {
            answer.push_back(user[v[i].user_id] + "님이 나갔습니다.");
        }
    }
    return answer;
}
 

 

문자열 파싱에 대해 알아볼 수 있는 문제였습니다.

+ Recent posts