BOJ의 채점 프로그램은 C++로 구현했습니다.
예전에, 언어가 몇 개 되지 않을 때는, 다음과 같은 방식으로 채점해야 하는 언어가 Java인지 아닌지 판별했습니다.
if (language_id == 3)
현재 Java의 시간 제한은 +5초를 주고 있는데, 이걸 구현 하려면 다음과 같은 형식이 됩니다.
if (language_id == 3) { time_limit += 5; }
점점 언어가 많이 추가되었고, Java를 이용해서 실행하는 언어가 조금 많아지게 되었습니다. 지금 BOJ에는 Java, Scala, Clojure, Rhino, Kotlin, Gosu가 있네요. 그럼, 코드는 이런식으로 변경하면 되겠습니다.
if (language_id == 3 || language_id == 15 || language_id == 32 || language_id == 34 || language_id == 69 || language_id == 80)
Java로 실행하는 언어는 채점 방식을 다른 언어와 다르게 진행하고 있기 때문에, 위의 if문은 여러 군데에 필요하게 됩니다.
문제는 언어가 추가되었을 때입니다. 저 부분을 모두 찾아서 if문에 하나씩 더 추가해야 합니다. 유지보수의 난이도가 매우 상승하게 됩니다.
Python을 사용하면, 다음과 같이 구현할 수 있지 않을까요?
if language_id in [3, 15, 32, 34, 69, 80]: pass
코드의 길이는 줄었지만, 리스트를 매번 바꿔야하는 건 똑같기 때문에, 변수를 하나 사용할 수 있을 것 같습니다.
java_family = [3, 15, 32, 34, 69, 80] if language_id in java_family: pass
일단은 좋은 것 같습니다. 이걸 C++로 구현해 보려고 합니다.
std::vector<int> java_family = {3, 15, 32, 34, 69, 80}; bool is_java_family(int language_id) { for (int lang : java_family) { return true; } return false; }
어차피 언어의 개수가 많지 않기 때문에, vector
나 set
이나 큰 차이는 없을 것 같지만, 간단하게 구현하기 위해서 set
을 사용해 봅시다.
std::set<int> java_family = {3, 15, 32, 34, 69, 80}; bool is_java_family(int language_id) { if (java_family.count(language_id) > 0) return true; return false; }
구현하다 보면 여러가지 경우를 검사해야 하기 때문에, 다른 변수와 함수도 필요할 것 같습니다. 대표적으로 gcc를 사용하는 언어와 clang을 사용하는 언어들이 있겠네요.
std::set<int> gcc_family = {88, 0, 1, 49, 84, 75, 10, 64, 27, 87, 23}; bool is_gcc_family(int language_id) { if (gcc_family.count(language_id) > 0) return true; return false; } std::set<int> clang_family = {59, 60, 66, 67, 77, 85}; bool is_clang_family(int language_id) { if (clang_family.count(language_id) > 0) return true; return false; }
매번 이렇게 함수와 변수를 추가하는 것도 머리가 아프니, 함수를 하나만 사용하는 방식으로 변경해보려고 합니다.
map
을 이용해서 변수를 하나만 사용해 언어 정보를 저장해봅시다.
std::map<std::string, std::set> language_dict = { {"java", {3, 15, 32, 34, 69, 80}}, {"gcc", {88, 0, 1, 49, 84, 75, 10, 64, 27, 87, 23}}, {"clang", {59, 60, 66, 67, 77, 85}} };
그럼 이제 새로운 함수를 이용해서 구현을 해볼 수 있을 것 같습니다.
bool contain(int n, std::set<int> s) { if (s.count(n) > 0) return true; return false; } bool is(int language_id, std::string key) { if (language_dict.count(key) > 0) { auto &s = language_dict[key]; if (contain(language_id, s)) return true; } return false; }
이제 다음과 같이 구현할 수 있을 것 같습니다.
if (is(language_id, "java")) if (is(language_id, "gcc"))
실제로는 클래스를 이용해 언어 정보를 저장하기 때문에, if (language.is("gcc"))
와 같은 식으로 구현했습니다.