문제
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;
}