etc

코드포스 첫 도전 후기(부제: Hacked...)

Jimin Hong 2023. 10. 7. 17:26

동기

 

백준 풀 때, 닉네임에 색깔 있는 유저들의 깔끔하고 예쁜 코드를 보면서 나도 저렇게 되고 싶다는 생각을 항상 했었다.

 

백준 아이디에 코드포스(Codeforces) 아이디를 연동하면 코드포스 레이팅에 따라 닉네임 색깔이 바뀐다고 한다.

 

 

https://www.acmicpc.net/blog/view/90

 

solved.ac 티어 v. 코드포스 레이팅 (~2020. 2. 3)

solved.ac 티어 v. 코드포스 레이팅에 대한 통계를 작성해봤습니다. 표본 n = 624이고, R2 = 0.60으로 유의미한 상관관계가 발견되었습니다. 레이팅 최대치로 계산했을 때에는 레이팅 1500 이하 분들의

www.acmicpc.net

 

몇 년이 지난 자료긴 하지만, G2~G1 정도가 그린이라고 한다.

이번에 골드도 달았겠다, 나도 그린 목표로 코드포스에 가입해봤다(물론 그린을 달기에는 공부가 정-말 많이 필요한 상태라는 걸 알고 있다...그래도 일종의, 새로운 동기 부여가 되었으면 좋겠다는 마음으로 시작한 거다!)

 


 

코드포스 설명

 

Problemset 페이지에서 이전에 출제된 문제들을 풀어볼 수 있었다.

 

각 문제에는 푼 사람들의 레이팅을 고려하여 난이도가 매겨지는데,

문제들을 난이도 순으로, 푼 사람 많은 순으로 정렬할 수 있다. 난이도 필터도 있다.

 

C++ 코드는 언어 옵션을 GNU G++~로 선택하고 제출하면 된다.

 

 

 

Contest 페이지에서는 앞으로 진행될 예정인 대회 정보를 확인하고, 참여할 수 있다.

외국 사이트다 보니 대회는 주로 밤 시간에 진행된다.

난이도는 Div.1 > Div.2 > Div.3이다. 이에 따라 영향을 주는 레이팅의 범위가 서로 다르다.

 


Hacked?

 

나는 수강신청 이슈로 반강제 미라클모닝 중(ㅠㅠ)이어서 당일날 바로 도전해볼 수는 없었고, 주말에 미리 낮잠을 자고 와서 도전해봤다.

9월 24일 23시 35분부터 진행된 Div.2 대회였다.

스샷은 없지만 한 시간 가까이 걸려 A문제를 맞혔고, B문제는 풀지 못하고 대회가 종료되었다.

 

첫 대회에 Div.2 수준이었는데, 그래도 한 문제를 맞혔으니 나쁘지 않았다고 생각하며 잠들었다.

그런데!

 

 

 

 

다음 날

 

 

핵? 해킹이요?

 

 

맞은 줄 알았던 A문제가 오답으로 처리되어 있었다...

 

어떻게 된 일인지 검색해보니, 다른 참가자로부터 반례가 들어온 거였다. 이걸 Hack이라고 부른다고 한다.

더보기

 

대회 시간 내에는 10여 개의 테스트 케이스(Pretest)만 이용해서 채점하기 때문에, 코드가 완벽하지 않더라도 통과될 수 있다. 대회가 끝난 후 통과 코드들을 전체 테스트 케이스(System test)로 다시 채점한다. 이때 다른 참가자의 통과 코드를 틀리게 할 수 있는 반례 테스트 케이스를 찾는 데에 성공하면 추가 점수를 얻을 수 있다(대회 중에도 가능하고, 대회가 끝나고 12시간 이내에 가능하다). 이게 바로 Hack이다. Hack 시도에 사용된 입력은 그 문제의 System test case에 자동으로 추가된다. 이 System test까지 통과해야 비로소 그 문제를 맞힌 것으로 인정되는 거다.

 

오마이갓. 어떤 똑똑하신 자비없는 분이 기상천외한 반례를 생각해내신 게 분명했다. 

 

 


 

사건의 전말... 그리고 깨달은 점

 

A문제 코드를 다시 읽어봤다.

원인은 생각보다 간단한 곳에 있었다. 참고로 이 문제는 1879A Rigged! 라는 문제로, 적당한 바벨의 값 w를 구해 출력하는 문제다.

 

https://codeforces.com/submissions/jm0309

 

Personal submissions - Codeforces

 

codeforces.com

 

이 문제에서는 출력하는 값이 0이어서는 안된다. 그런데 내가 짠 코드는,

1

2

1 5

2 1

과 같은 테스트 케이스에서

1을 출력해야 하는데 0을 출력한다.

 

다른 line은 건드리지 않고 마지막 줄의 sP - 1에서 -1만 지우고 재제출하니 정답처리되었다.

이 1을 굳이 빼주어서 출력값 범위 조건을 벗어나게 된 데에는, 물론 내가 저 문제 풀 당시에 저 반례의 경우를 고려하지 못했어서...도 맞지만, 좀 더 근본적인 이유가 있었다.

바벨의 무게 w가 i번째 운동선수의 힘 si보다 확실하게 크면, i번째 운동선수는 바벨을 들어올리지 못한다. 라는 문장을,

바벨의 무게 w보다 i번째 운동선수의 힘 si가 확실하게 크지 않으면, i번째 운동선수는 바벨을 들어올리지 못한다. 라고 잘못 이해해서 저렇게 접근한 것이다.

즉, 내가 문제를 제대로 이해했다면 출력값 이슈는 일어나지 않았을 거다.

허탈했다.

 

 

이번 일로 두 가지 교훈을 얻었다.

 

1.

영어에 익숙해져야 한다.

 

사실 문제가 한국어였다면 이런 실수를 하지 않았을 거란 생각이 든다. 안 그래도 문제가 영어다보니 문제를 이해하는 데에 시간이 오래 걸렸는데 말이다...

 

부끄럽게도 그동안 내가 영어를 못하는 편은 아니라고 생각했었는데, 그건 엄청난 착각이었다는 걸, 그리고 영어 점수와 영어를 익숙해하는 것은 서로 다르다는 걸 몸소 느꼈다. 외국어 실력은 자주 접할수록 늘어난다고 하지 않는가. 그 의미를 조금 깨달았다. 

그래서, 코드포스를 통해서 코딩 실력과 영어 실력을 동시에 키우고 싶다는 욕심(그리고 그린도 꼭 달고 싶다)이 더 커졌다.

 

 

2.

코드가 통과되었다고 해서 무조건 그대로 믿으면 안된다.

 

그동안 코딩 문제를 만든다든가, 테스트 케이스를 추가한다든가 하는 건 정말 초고수들만의 영역이라고 생각했었다(물론 그런 분들은 초고수가 맞다. 따봉) 그런데 이번에 문제를 잘못 이해하고 짠 코드가 통과되는 걸 보면서, 그리고 직접 반례를 찾아내는 경험을 해보면서 내 코드를 항상 의심해야 한다는 걸 깨달았다. 테스트 케이스로 잡아내지 못하는 미묘한 차이가 결정적인 차이를 불러올 수 있다는 사실을 실감했다.

 

 

결국 레이팅 현황은 위와 같다.

첫 6판에는 보너스 점수를 준다고 하는데(아 준 거 맞냐고 ㅋㅋ) ...분발하도록 하겠다!