[BOJ/C++] 20210: 파일 탐색기

다곰·2023년 10월 13일
0

우당탕탕 코테준비

목록 보기
86/98

🏅 Gold 5

✏️ 최종 솔루션

⭐️ 정렬

  1. 문자열을 입력받으면 이를 문자와 숫자로 나눠서 string 이중 vector 에 입력하기
    ex) ab123c ➡️ a, b, 123, c
  2. 비교할 두 string vector 중에 작은 size 만큼 탐색하여 비교기준 충족여부에 따라 다른 값 return
    ➡️ 작은 size 만큼 탐색했는데도 비교가 안됐다는 것은 작은 쪽에 문자를 이어 붙인 형태이므로 vector size 오름차순으로 return
    ex) 1, 2, 31, 2, 3, c 를 비교하면 0~3번을 탐색하는 동안 결론이 안 나기 때문에 size가 더 큰 123c 가 뒤에 올 것이기 때문에 vector size가 작은 vector가 먼저 오는 것
  3. 현재 인덱스의 문자열이 다를 경우 비교 기준
    1️⃣ 둘 다 숫자인 경우
    1) 두 숫자 앞의 0을 제외하여 문자열 저장
    2) 0을 뺀 문자가 같으면 같은 숫자이기 때문에 0의 개수가 작은 순으로 return
    ❗️ 이때는 원본 문자열 size 가 큰 문자열이 0의 개수가 큰 것이기 때문에 문자열 size 에 따라 오름차순 정렬
    3) 숫자는 자리수가 클수록 큰 수이기 때문에 첫번째 문자열의 size가 크면 true, 두번째 문자열의 size가 크면 false return
    ❗️ vector의 정렬은 기본적으로 오름차순인데 두번째 문자열이 더 크면 내림차순이 되기 때문에 false return 하는 것
    2️⃣ 문자와 숫자인 경우: 본래 정렬대로 문자가 앞에 오도록 오름차순 정렬
    3️⃣ 둘 다 문자인 경우
    1) 이미 첫 단계에서 두 문자가 같은 경우를 배제했기 때문에 알파벳을 대문자로 변경했을 때 같으면, 소문자와 대문자인 것인데 대문자가 가중치가 더 작기 때문에 이를 오름차순으로 정렬
    2) 알파벳이 다르면 알파벳 순으로 정렬하기 위해 대문자로 변환한 문자를 오름차순 정렬
    ❗️ 문자를 대문자로 변환하여 비교하는 이유는 보통 문자의 우선순위는 대문자 > 소문자 인데 AaBb 처럼 알파벳 > 대문자 > 소문자 로 정렬해야 하기 때문

📌 self feedback

정렬 기준이 방대할 경우, 커스텀하는데 익숙하지 않았음
문자열 문제는 감이 안 오면 정말 문제에서 하라는 대로 그대로 흐름을 따라가야 함
문자열을 분할할 때, 한 문자씩 분할하지만 숫자는 통으로 분할하는 것이 관건이었음

✏️ 최종 code

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

bool cmp(vector<string>& v1, vector<string>& v2) {
    int len=min(v1.size(),v2.size());

    for(int i=0;i<len;i++) {

        if(v1[i]!=v2[i]) {
            // 숫자 비교

            if(v1[i][0]>='0'&&v1[i][0]<='9'&&v2[i][0]>='0'&&v2[i][0]<='9') {

                string s1="",s2="";

                for(int j=0;j<v1[i].size();j++) {
                    if(v1[i][j]!='0') {
                        s1=v1[i].substr(j);
                        break;
                    }
                }

                for(int j=0;j<v2[i].size();j++) {
                    if(v2[i][j]!='0') {
                        s2=v2[i].substr(j);
                        break;
                    }

                }

                if(s1==s2) return v1[i].size()<v2[i].size();
                else {
                    if(s1.size()<s2.size()) return true;
                    else if(s1.size()>s2.size()) return false;
                    else {
                        if(s1<s2) return true;
                        return false;
                    }
                }
            }
            // 문자 vs 숫자
            if((v1[i][0]>='0'&&v1[i][0]<='9')||(v2[i][0]>='0'&&v2[i][0]<='9')) return v1[i]<v2[i];

            if (toupper(v1[i][0]) == toupper(v2[i][0])) return v1[i] < v2[i];
            
            return toupper(v1[i][0]) < toupper(v2[i][0]);

        }
    }
    
    return v1.size()<v2.size();

}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n;
    cin >> n;
    vector<vector<string>> v;
    for(int i=0;i<n;i++) {
        string s;
        cin >> s;

        string tmp="";
        vector<string> vs;
        for(int j=0;j<s.size();j++) {
            // 숫자
            if(s[j]>='0'&&s[j]<='9') tmp+=s[j];
            else {
                if(tmp!="") vs.push_back(tmp);
                tmp=s[j];
                vs.push_back(tmp);
                tmp="";
            }
        }

        if(tmp!="") vs.push_back(tmp);
        v.push_back(vs);

    }

    sort(v.begin(),v.end(),cmp);

    for(int i=0;i<v.size();i++) {
        for(int j=0;j<v[i].size();j++) {
            cout << v[i][j];
        }
        cout << endl;
    }

}
profile
다교미의 불꽃 에러 정복기

0개의 댓글