PS/자주 하는 답변

반례에 의존하지 마세요.

djm03178 2023. 6. 15. 17:12

이번 글은 실제로 많이 하는 답변이라기보다는 대다수의 질문자들께 드리고 싶은 조언을 담은 글입니다.


질문글을 보다 보면 그 중 반 이상은 '반례를 찾아달라'는 내용이 거의 전부인 것을 목격하게 됩니다.

 

물론 아무리 봐도 완벽한 내 코드가 틀리는 케이스가 무엇인지 알게 되면 답답함이 해소되는 것은 당연하고, 반례를 바탕으로 디버깅도 훨씬 수월하게 진행할 수 있기 때문에 반례를 부탁하게 되는 심리는 매우 자연스럽습니다.

 

하지만 저는 이런 당장의 시원함보다는 반례를 알려주지 않는 시스템이기 때문에 얻을 수 있는 것들을 얻어가는 것이 중요하다고 생각합니다.

 

BOJ는 틀린 케이스가 무엇인지 알려주지 않는 사이트로 유명(?)한데, 이는 결코 데이터가 저작권이 있어서 유출되기를 꺼리기 때문이 아닙니다. 데이터에 맞게 코드를 fitting해서 제출할 수 있다는 문제도 있긴 하나 어디까지나 부차적인 이유입니다. BOJ에서 데이터를 공개하지 않는 가장 근본적인 이유는 그것이 여러분의 문제 풀이 실력 향상에 도움이 되기 때문입니다.

 

문제를 못 풀게 막아세우는데 그게 어떻게 도움이 되냐고요? 다음과 같은 근거들을 제시할 수 있습니다.

  • 문제 풀이 실력이라는 것은 단순히 문제를 푼 개수에 비례하는 것이 아닙니다. 문제들을 풀면서 생각하고 코딩하는 과정 전부가 공부 과정이자 실력을 향상시키는 과정인 것입니다.
  • 알고리즘 대회든, 코딩 테스트든, 현업이든, 취미로 개발을 하든 우리는 앞으로 '반례'가 주어지지 않은 환경에 놓이게 되는 것이 일반적입니다. 이런 상황에서 필요한 역량이 과연 누군가 '반례'를 제시해 줄 때까지 가만히 기다리고 있는 것일까요? 그렇지 않을 것입니다. 여러분에게는 스스로 자신의 코드가 완벽해지도록 처음부터 튼튼한 구조의 프로그램을 작성하고, 실수하지 않도록 조심하고, 스스로 코드의 약점을 찾아낼 수 있는 종합적인 능력이 필요합니다. 
  • 그러면 데이터는 일단 공개해두고 보고 싶은 사람만 보면 되지 않을까요? 위에서도 언급했지만 사람 심리라는 것이 그렇지 않습니다. 당장 눈앞에 답답한 마음이 뻥 뚫릴 수 있는 길이 열려있는데 이 유혹을 끝까지 참을 수 있는 사람이 얼마나 있을까요?

하지만 반례가 없으면 도대체 어떻게 문제점을 찾아나서야 할까요? 무언가 틀렸다고는 하는데, 어디가 틀렸는지 모르니 막막한 것은 당연합니다. 그럼에도 불구하고 이 난관을 스스로 헤쳐나가는 것이 중요합니다. 코드의 문제점을 찾기 위해 코드전체를 다시 돌아보는 과정 전체가 곧 실력을 향상시키는 과정 그 자체이기 때문입니다.

  • 반례를 스스로 만들어보세요. 잠깐, 지금까지 반례에 의존하지 말라고 해놓고 이건 무슨 말일까요? 반례에 의존하지 말라는 것은 그저 누군가가 제시해 준 반례를 패시브하게 받아들이는 데에 그치지 말라는 뜻이지, 반례를 스스로 찾는 과정 자체는 연습에 매우 중요한 요소입니다. 반례를 직접 만들기 위해서는 어떤 형태의 데이터들이 존재할 수 있는지를 스스로 생각해야 할 뿐 아니라, 그러한 데이터가 내 코드에서 문제를 일으키지는 않을지 끊임없이 스스로 리뷰를 진행하게 됩니다. 반례를 만들면서 얻어가야 할 것은 그렇게 내 코드와 그 로직을 계속해서 되돌아보면서 정말 이 코드가 문제의 요구 사항을 완벽하게 충족시킬 수 있는지를 다양한 케이스에 대해 생각해보는 과정 그 자체인 것이지, 단순히 이미 반례라고 누군가가 알려준 것을 통해 코드의 오류를 한 줄 고쳐 정답을 받는 것이 아닙니다.
  • 코드의 모든 부분이 의도대로 동작하고 있는지를 디버깅하세요. 예제가 잘 나온다고 해서 그 코드의 모든 부분이 정상적으로 내가 생각한 대로 동작했기 때문에 정답이 나온 것이 아닐 수 있습니다. 어딘가 잘못된 곳이 있었는데도 불구하고 그것이 예제에 대해서는 우연히 문제를 일으키지 않았을 수도 있고, 그 예제가 단순히 코드의 잘못된 분기점을 지나가지 않아서 문제가 없었던 것일 수도 있습니다. 코드의 중요한 포인트마다 모든 변수의 값이 내가 생각했던 그 값 그대로 정확하게 들어가고 있는지 출력문을 통해 확인하든, 디버깅 도구를 사용해서 브레이크포인트를 걸든 직접 확인해 보세요. 또한 모든 분기를 테스트 해보세요.
  • 로직을 되돌아보세요. 아무리 내가 생각한 로직을 코드로 제대로 구현했다고 해도 그 로직 자체가 틀렸다면 당연히 문제는 해결되지 않습니다. 처음부터 문제의 조건 전체가 아닌 오로지 예제만을 고려하면서 작성한 편향된 로직이지는 않은지, 이 로직이 문제의 조건 범위를 적절하게 커버하고 있는지 머릿속으로, 손으로 다시 한 번 검증하는 시간을 가지세요.
  • 코드를 다시 한 줄 한 줄 확인하세요. 웬만큼 쉬운 문제라고 해도 코드에는 기본적으로 수백 글자 이상이 들어갑니다. 이 많은 글자를 치는 동안 단순한 오타 하나조차 없을 거라고 생각하기는 어렵습니다. 단순히 그것이 컴파일 에러로 이어지지 않았다고 해서 올바른 코드가 된 것은 아닙니다. 정말 코드 어디에도 잘못 쓰인 곳이 없는지, 문법이나 라이브러리의 사용법을 정확히 모르면서 대충 쓰고 넘겼던 부분이 있지는 않은지, undefined behavior와 같은 요소는 없는지 등 코드 전체를 스스로 다시 리뷰하세요.

 

반례를 통해 정답을 받는 단편적인 성과보다는 처음부터 끝까지 스스로의 힘으로 코드의 최초 작성부터 코드와 로직의 리뷰, 버그 탐색 및 코드 수정까지의 전 과정을 수행함으로써 더 많은 것을 얻어갈 수 있기를 바라는 마음입니다.