채점 프로그램 개선하기

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

어차피 언어의 개수가 많지 않기 때문에, vectorset이나 큰 차이는 없을 것 같지만, 간단하게 구현하기 위해서 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"))와 같은 식으로 구현했습니다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

About Baekjoon

스타트링크 블로그에서 지루한 글을 담당하고 있습니다!