https://www.acmicpc.net/problem/2789
2789번: 유학 금지
아주 멀리 떨어져 있는 작은 나라가 있다. 이 나라에서 가장 공부를 잘하는 학생들은 모두 다른 나라로 유학을 간다. 정부는 최고의 학생들이 자꾸 유학을 가는 이유를 찾으려고 했다. 하지만,
www.acmicpc.net
🔔 문제 :
입력으로 주어진 단어를
"CAMBRIDGE" 이중 포함되는 알파벳을 없앤후 출력하면 되는 문제입니다.
입력값 LOVA -> 출력값 LOV
🔔 Kick Point :
각 알파벳을 넣어줘서, for문을 통해 일치하는 값이 있다면 입력값을 제한해주었습니다.
하지만 이런 코드는 또 너무 길고 지저분해서 다른 분들의 숏코딩을 찾아보았습니다.
비트연산자를 사용하는 코드를 발견하고 써먹어야겠다 싶어서 올립니다.
1. 쉽게 for문 사용
C++11이상 언어스타일은 for_each 반복문을 사용할 수 있습니다.
즉 for(char c : str) 을 통하여 string를 순회할 수 있습니다.
for(자료형 변수명 : 배열명) { 실행 코드 }
2. 비트마스크를 이용한 제한
AND 연산 &
NOT 연산 ~ 을 이용합니다.
'A' 'B' 'C' 'D' 'E' 'G' 'I' 'M' 'R' 인 문자열을 숫자 65를 빼서 비트로 나타내 보면
'A' - 65= 1
'B' - 65 = 2
'C' - 65 = 3
... 이렇게 일반 알파벳 순서로 나타낼 수 있습니다.
이를 1 << 왼쪽연산쉬프트를 통하여 비트로 바꿔준다면
1 << 'A' - 65 = 0000 0001
1 << 'B' - 65 = 0000 0010
1 << 'C' - 65 = 0000 0100
이런식으로 나타낼 수 있을 것입니다.
그렇다면 숫자 135519는 무엇일까요?
bitset을 통해 확인해보면
32bit에서 A, B, C, D, E, G, I, M, R의 차이값 만큼 왼쪽 쉬프트한 비트임을 알 수 있습니다.
그래서 if( ~t & (1 << (c - 65) ))구문을 통하여 제한하는 문자열을 쉽게 찾을 수 있음을 알게 되었습니다.
논외로 그리고 이 135519은
int tmp =0;
string s = "CAMBRIDGE";
for (char c : s) tmp += (1 << (c - 65));
이렇게 해서 숫자를 찾으면 되겠네요.
와 진짜 비트연산 완전 편리하고 좋네요. 잘알아두면 좋을 것 같습니다.
🔔 Code :
이전
#include <iostream>
using namespace std;
int main() {
char tmp;
char regulation[9] = {'C', 'A', 'M', 'B', 'R', 'I', 'D', 'G', 'E'};
while (cin >> tmp) {
for (int i = 0; i < 9; i++) {
if (tmp == regulation[i]) {
tmp = 0;
break;
};
}
if (tmp != 0) cout << tmp;
}
}
이후
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
int t = 135519;
cin >> s;
for (char c : s) if (~t & (1 << (c - 65))) cout << c;
}