Coding Interview/프로그래머스

[C++] 프로그래머스 [3차] 파일명 정렬 - 연속한 문자열 처리, 정렬함수 구현하기

2로 접어듦 2023. 1. 25. 00:56

문제

https://school.programmers.co.kr/learn/courses/30/lessons/17686#

리뷰

문제 유형: 구현, 문자열 처리, 정렬

 

주어진 두 문자열을 정렬하기 위한 커스텀 함수를 작성할 때 복사-붙여넣기 이후 수정하는 과정에서 동기화가 안 되었다. 조그마한 부분을 찾아내는 것이 힘드므로, 중복되는 부분은 약간의 생각 이후 함수화하는 것이 편리함을 깨달았다.

 

핵심

  • 연속한 문자열에서 문자와 숫자를 구분해낼 수 있는가 → sstream, strind indexing 후 += chararcter 연산 혹은 push_back
  • 문자열을 사전 순으로 정렬할 수 있는가
    → tolower를 사용할 수 있는가(프로그래머스 레퍼런스를 참고하면 되는데, std::transform을 이용한 lowercase 변형을 활용할 수 있다) 아래와 같이 커스터마이징 함수를 만들어 target string의 알파벳을 대/소문자 통일하여 만들 수 있다.
    대소문자가 통일된 문자열은 stringA.compare(stringB) < 0 일 때 string A가 사전순으로 앞선 것이므로, 이를 활용해서 정렬을 수행할 수 있다(이 또한 정렬 함수를 만들면 된다. 문자열의 길이가 달라도 앞 글자부터 비교를 진행함)
// 문자열 대소문자 통일시키기
char trans(char ch){
	return tolower(ch);
}

string make_lower(string tar_str){
	std::transform(tar_str.begin(), tar_str.end(), tar_str.begin(), trans);
    return tar_str;
}
  • HEAD-NUMBER 구성 이후 TAIL을 NUMBER와 구분할 수 있는지도 포인트이다.

 

코드

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <sstream>

using namespace std;
/*
string str_tolower(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(), 
                   [](unsigned char c){ return std::tolower(c); }
                  );
    return s;
}*/

char tr(char ch){
    return tolower(ch);
}

string str_tolower(string s){
    transform(s.begin(), s.end(), s.begin(), tr);
    return s;
}

pair<string, int> head_and_number(string s){
    pair<string, int> answer;
    string shead="", stail="";
    string sint;
    
    bool int_flag = false;
    for(int i=0; i<s.size(); i++){
        if(s[i] >= '0' && s[i] <='9'){
            int_flag = true;
            sint += s[i];				// char을 += 하는 것이므로 결과도 string임에 주의!
        }
        else if(!int_flag){
            shead += s[i];
        }
        else
            break;
    }
    return {str_tolower(shead), stoi(sint)};
}

bool comp(pair<string, int> a, pair<string, int> b){

    pair<string, int> aconv = head_and_number(a.first);
    pair<string, int> bconv = head_and_number(b.first);
    
    string astr = aconv.first, bstr= bconv.first;
    int ainti = aconv.second, binti = bconv.second;
    
    // head sort
    if(astr.compare(bstr) != 0)
        return (astr.compare(bstr) < 0) ? true:false;
    
    // number sort
    if(ainti != binti)
        return ainti < binti;
    
    return a.second < b.second;
}

vector<string> solution(vector<string> files) {
    vector<string> answer;
    vector<pair<string, int>> files_temp;
    
    // files의 순서를 기억하기 위한 벡터
    int i=1;
    for(auto& iter : files)
        files_temp.push_back({iter, i++});
    
    sort(files_temp.begin(), files_temp.end(), comp);
    
    for(int i=0; i<files_temp.size(); i++)
        answer.push_back(files_temp[i].first);
    
    return answer;
}