언어마다 천차만별인 문자열 관련 기능들을 알아야만 풀 수 있는 문제이므로..
기초적인 대략의 풀이만 참고한다.
소문자가 대문자+32 라는 것을 알아야만 할 것이다.
시도
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int var_mode;
string input;
string camel, snake, pascal;
cin >> var_mode >> input;
switch (var_mode)
{
// camel
case 1:
camel = input;
//snake
for(int i=0; i<input.size();i++){
if('a' <= input[i] && input[i]<= 'z'){
snake+=input[i];
}
else{
snake+='_';
snake+= input[i]+32;
}
}
//pascal
pascal = input;
pascal[0] = pascal[0]-32;
break;
// snake
case 2:
snake = input;
//camel
for(int i=0; i<input.size();i++){
if('a' <= input[i] && input[i]<= 'z'){
camel+=input[i];
}
else{
camel+= input[i+1]-32;
i=i+2;
}
}
//pascal
pascal = camel;
pascal[0] = pascal[0]-32;
break;
// pascal
case 3:
pascal = input;
//camel
camel = pascal;
camel[0] = camel[0] + 32;
//snake
for(int i=0; i<input.size();i++){
if('a' <= input[i] && input[i]<= 'z'){
snake+=input[i];
}
else{
if(i!=0){
snake+= '_';
}
snake+= input[i]+32;
}
}
break;
}
cout << camel << "\n" << snake << "\n" << pascal;
return 0;
}
틀렸는데 왜인지 모르겠다.
반례도 적다. 심지어 저 반례도 통과했다.
위기다.
카멜표기법을 스네이크나 파스칼로 변환하는 것에는 문제가 없을 듯 하다.
카멜에서 파스칼로 변환시, 그냥 맨 앞문자만 대문자로 바꾸면 되고, 작동하고,
카멜에서 스네이크로 변환시, 카멜의 맨 앞글자가 소문자라서 Camel _camel 이런 경우도 존재할 수가 없다.
스네이크를 카멜, 파스칼로 변환하는 것에는?
스네이크를 카멜로 바꾸는데에, 언더바를 무시하고, i+1인 다음 문자의 값을 -32를 하여 대문자로 만든다. 그리고, i를 문자의 2칸 뒤로 간다.
이 경우, 맨 앞문자가 대문자가 될 일은 절대 없으므로 여기서 오류는 나지 않을 것이다.
i를 문자의 2칸 뒤로 간다는 부분이 문제가 될 수도 있겠다는 생각이다.
length 이후의 값으로 넘어간다면?
hello_c인 경우가 되겠다.
전혀 문제 없다.
그리고 카멜이 문제가 없다면 파스칼도 있을 수가 없는데,
카멜의 맨 앞글자만 또 바꾸면 파스칼이 되기 때문이다.
파스칼을 카멜로 바꾸는 경우, 역시 맨 앞글자만 소문자로 만들면 된다.
파스칼을 스네이크로 바꾸는 경우, 대문자인 부분을 _
를 추가하고,
소문자인 문자로 바꿔서 추가하면 되는데,
PasCal인 경우, _pas_cal일 수가 있어서 if문으로 인덱스가 0이면 추가하지 않도록 했다.
그리고 snake라서 소문자를 추가하도록 했는데...음..
문제를 모르겠다!!
조건을 봐도, 연속해서 _ _ 이렇게 언더바가 사용되는 경우도 없을 뿐더러,
마지막에 언더바가 나올 수가 없다. 항상 소문자를 추가하므로..
해결
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int var_mode;
string input;
string camel, snake, pascal;
cin >> var_mode >> input;
switch (var_mode)
{
// camel
case 1:
camel = input;
//snake
for(int i=0; i<input.size();i++){
if('a' <= input[i] && input[i]<= 'z'){
snake+=input[i];
}
else{
snake+='_';
snake+= input[i]+32;
}
}
//pascal
pascal = input;
pascal[0] = pascal[0]-32;
break;
// snake
case 2:
snake = input;
//camel
for(int i=0; i<input.size();i++){
if('a' <= input[i] && input[i]<= 'z'){
camel+=input[i];
}
else{
camel+= input[i+1]-32;
i=i+1;
}
}
//pascal
pascal = camel;
pascal[0] = pascal[0]-32;
break;
// pascal
case 3:
pascal = input;
//camel
camel = pascal;
camel[0] = camel[0] + 32;
//snake
for(int i=0; i<input.size();i++){
if('a' <= input[i] && input[i]<= 'z'){
snake+=input[i];
}
else{
if(i!=0){
snake+= '_';
}
snake+= input[i]+32;
}
}
break;
}
cout << camel << "\n" << snake << "\n" << pascal;
return 0;
}
풀이
찾았다.
+1만 했었어야 했다. 왜?
_를 만나는 경우, 언더바가 있는 곳이 i번째이고,
i+1번째가 다음 문자인데, 다음 문자도 건너 뛴 곳으로 가려면,
i+1로 i를 만들어놔야, for문 줄에서 바로 1이 또 추가가 되므로 i+2로 예상한 곳으로 가게 된다.
그 전에는 i+3으로 갔던 것임..
백준에 반례가 없는 경우가 제일 무서운 것 같다.
CPP Map관련 함수 모음
https://life-with-coding.tistory.com/305
https://kimcoder.tistory.com/122
https://blockdmask.tistory.com/87
iterator
https://velog.io/@sputnikel0221/C-6%EC%9D%BC%EC%B0%A8-2
해결
#include <iostream>
#include <map>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int sum = 0;
int num;
int max = 0;
int max_key;
map<int, int> appearMap;
for(int i=0;i<10;i++){
cin >> num;
//찾지 못한 경우
if(appearMap.find(num) == appearMap.end()){
appearMap.insert({num, 1});
}
else{
appearMap[num] += 1;
}
sum += num;
}
//map<int,int>::iterator == auto
for(auto iter = appearMap.begin(); iter!=appearMap.end(); iter++){
if(max < iter->second){
max = iter->second;
max_key = iter->first;
}
}
cout << sum/10 << "\n" << max_key;
return 0;
}
풀이
한 번에 풀게 되었다.
평균과 최빈값을 구하는 문제인데, 평균은 어려운게 아니고,
최빈값을 어떻게 구할지가 까다로웠는데, map구조가 생각났고,
map을 통해서 쉽게 구현할 수 있었다.
map라이브러리를 추가하고, <int,int> 구조의 map을 만들었다.
각 입력 숫자들을 key로 사용할 것이고, 빈도수를 value로 사용할 것이다.
appearMap.find(num) == appearMap.end() 구문을 통해, 찾지 못한 경우를 알 수 있었다.
map.find를 실패하면, map.end값으로 설정된다고 하여, 해당 if문을 작성할 수 있었다.
appearMap[num] += 1;
기존에 key가 존재했다면, 해당 num이라는 key값에 해당하는 map의 인덱스의 값에, 1을 추가한다.
당연히 value가 int형이기 때문에 가능한 일.
string이었다면, 문자가 한개씩 뒤에 추가되도록 구현도 가능할 듯..
이 부분이 가장 의미있다고 생각하는데, iterator를 사용한다.
iterator는 간단히 말하면, 자료형을 순회할 목적으로 만들어졌고,
자료형마다 쓰이는 이름이 iterator로 같지만 원리는 다르게 동작하도록 overload되었다.
여기서 auto로 간단히 적었지만, map<int,int>::iterator의 자료형을 가지고 있고,
map의 값을 pair로 담을 수 있는 듯 하다. 각 원소에 접근도 가능한데,
first는 key값이고, second는 value값을 의미한다.
https://www.acmicpc.net/problem/2930
스킵 - 문제 자체가 설명도 부실하고, 모호한 표현이 많아서 이해가 되질 않는다.
심지어는 예시나 반례도 부족하고...
5
가위 가위 보 보 바위
보 보 바위 바위 가위
바위 바위 가위 가위 보
처음은 그냥 순서 그대로 감
승승승승승
패패패패패 => 10점
두번째는 상근이 순서바꿈
보 보 바위 가위 가위
보 보 바위 바위 가위
바위 바위 가위 가위 보
비비비패비 >4점
승승승비패 > 7점 => 11점?
시도
#include <iostream>
#include <map>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
map<char, int> strmap;
int max = 0;
char max_char;
int same_count = 0; //같은 빈도수 체크
string s_input;
cin >> s_input;
for(int i=0;i<s_input.length();i++){
if('A' <= s_input[i] && s_input[i] <= 'Z'){
if(strmap.find(s_input[i])==strmap.end()){
strmap.insert({s_input[i], 1});
}
else{
strmap[s_input[i]] += 1;
}
}
else if('a' <= s_input[i] && s_input[i] <= 'z'){
if(strmap.find(s_input[i]-32)==strmap.end()){
strmap.insert({s_input[i]-32, 1});
}
else{
strmap[s_input[i]-32] += 1;
}
}
}
map<char, int>::iterator iter;
for(iter = strmap.begin(); iter!=strmap.end(); iter++){
if(max <= iter->second){
max = iter->second;
max_char = iter->first;
}
}
for(iter = strmap.begin(); iter!=strmap.end(); iter++){
if(max == iter->second){
same_count++;
}
}
if(2 <= same_count){
cout << '?' << same_count;
}
else{
cout<< max_char;
}
return 0;
}
baaa가 다음과 같이 성공적으로 map이 되었다.
하지만 정답은 아님.
왜일까?
해결
가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.
에서 ?만 출력해야했는데 이상한 코드를 작성했었던 것이다.
Mississipi
#include <iostream>
#include <map>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
map<char, int> strmap;
int max = 0;
char max_char;
int same_count = 0; //같은 빈도수 체크
string s_input;
cin >> s_input;
for(int i=0;i<s_input.length();i++){
if('A' <= s_input[i] && s_input[i] <= 'Z'){
if(strmap.find(s_input[i])==strmap.end()){
strmap.insert({s_input[i], 1});
}
else{
strmap[s_input[i]] += 1;
}
}
else if('a' <= s_input[i] && s_input[i] <= 'z'){
if(strmap.find(s_input[i]-32)==strmap.end()){
strmap.insert({s_input[i]-32, 1});
}
else{
strmap[s_input[i]-32] += 1;
}
}
}
map<char, int>::iterator iter;
for(iter = strmap.begin(); iter!=strmap.end(); iter++){
if(max <= iter->second){
max = iter->second;
max_char = iter->first;
}
}
for(iter = strmap.begin(); iter!=strmap.end(); iter++){
if(max == iter->second){
same_count++;
}
}
if(2 <= same_count){
cout << '?'; // 이부분..
}
else{
cout<< max_char;
}
return 0;
}
풀이
단순히 디버그용 출력 메세지를 그대로 붙여넣었던 것이었다.
확실히 Map이 시각적으로 보이니까 훨씬 동작원리를 빠르게 캐치할 수 있게 된다.
브론즈4부터 브론즈1까지 풀었다.
특별한 알고리즘을 사용하지는 않았고, 브루트포스, 버블정렬외에는 사용하지 않았다.
실버 4까지가 프로그래머스 1정도인데, 분발할 필요가 있어보인다.
입출력관련 2가지 명령어
CPP 이미 선언한 배열의 초기화는 fill_n을 사용할 것..
브루트포스 - 무식하게 for문 돌림 / 그 for문에서 원하는 값만 가지고 빠져나오는 기술이 필요
버블정렬 - 쉬움, 다만 헷갈릴 수도 있음.
문자열 대소문자는 32차이, 소문자가 값이 더 큼
문자열 + 문자 = 문자열 뒤에 문자 붙이기
문자열 + 정수 = 문자열 아스키코드에 정수 더하기
문자열의 비교연산자 = 문자열 아스키코드를 비교
문자열.size를 통해서 0부터 문자열.size까지 문자열[i]를 돌 수 있다.
해당 원소는 문자이다.
Map.find(키)로 해당 키값을 찾지 못한다면, Map.End()값과 같아진다.
이를 활용하여 if문 가능
Map[키]로 직접 키에 해당하는 value값을 수정할 수 있다.
value값처럼 연산도 가능하다.
iteraor를 사용하여 순회가 가능하다.
auto iter = Map.begin(); iter!=Map.end(); iter++
여기서 iter는 값의 쌍이고, first는 key, second는 value를 의미한다.