알고리즘/코딩테스트를 독학하는 방법에 대한 개인적인 생각

강의를 만들다가 갑자기 생각이 든게 있어서 까먹기 전에 글을 씁니다. 이 글의 예상 독자는 코딩테스트를 준비하고 계신 분들입니다. SCPC나 ICPC와 같은 대회에서 수상을 노리고 꾸준하게 준비하고 계신 분들에게는 제가 감히 조언을 할 레벨이 아닌 것 같습니다.

 

몇년 전부터 알고리즘이 핫해지면서 IT분야 취준생에게는 코딩테스트 대비가 거의 필수가 되었고 당장 취업과는 크게 상관이 없더라도 취미삼아, 혹은 개발 능력 함양을 위해 BOJ나 기타 플랫폼에서 문제를 꾸준히 푸는 분들이 많이 보입니다.

 

취미로 PS(=Problem Solving) 공부를 하시는 분들이야 크게 압박감 없이 문제 푸는 과정을 즐기면서 할 수 있겠지만 현실적으로 코딩테스트를 어떻게든 합격해야하는 취준생 입장에서는 특히 요즘과 같이 취준이 어려운 시기에 정말 스트레스가 이만저만이 아닐 것 같습니다.

 

그나마 다행이라고 한다면 코딩테스트가 활성화되기 훨씬 전부터도 PS 분야는 꾸준히 수요가 있었기에 관련 시스템이 잘 만들어져 있고 추가적으로 점점 PS 분야에 관심을 가지는 사람들이 늘어나 간단한 검색만으로도 PS 분야를 공부할 수 있는 다양한 자료를 접할 수 있습니다. 특히 백준 온라인 저지에는 기출을 비롯한 수많은 문제들이 존재하고 있고 인터넷에 검색해보면 풀이가 곳곳에 있습니다. 심지어 다양한 유/무료 인강이 많고 내가 궁금한 주제에 대한 양질의 게시글 또한 그다지 어렵지 않게 찾을 수 있습니다.

 

여기까지만 보면 코딩테스트를 준비하는게 너무나 쉬워보이는데 막상 독학을 하려고 하면 생각보다 어려움이 많을 것입니다. 당장 저도 누군가가 코딩테스트를 어떻게 준비해야하냐고 물어보면 개념을 습득한 후 관련 문제들을 주구장창 풀면 된다고 답변한 적이 여러 번 있지만 지금 생각해보면 그렇게 단순하게 답변할 수 있는 질문은 아닌 것 같습니다.

 

사실 아예 프로그래밍 언어를 숙달하지 못한 경우는 논외로 하고 정상적인 컴퓨터공학의 교육과정을 따라왔다면 어느 정도 수준의 문제까지는 큰 어려움 없이 해결할 수 있을 것입니다. 맨 처음에는 코드로 문제를 푸는게 익숙하지 않은 것에서 오는 어려움이 조금 있을 수 있겠지만 코딩 난이도가 높지는 않기 때문에 금방 적응해서 문제를 풀어나갈 수 있습니다.

 

하지만 그렇게 난이도를 높여가다가 삼성 A형 기출 스타일의 문제들을 풀려고 할 때 아마 고비가 찾아올 것입니다. 제가 주로 본 패턴은 이렇습니다.

 

1. 코딩 테스트 문제를 풀려고 시도함(ex : 2048 (Easy), 감시)

2. 문제의 내용을 보면 무엇을 해야하는지는 명확하기 때문에 적당히 설계를 하고 코드 작성에 들어감

3. 짜다보니 꼬이고 코드 길이가 한없이 길어짐

4. 기껏 완성한 후 돌렸는데 예제가 안나옴

5. 코드 중간중간에 끊임없이 출력문을 넣어서 잘못된 부분은 간신히 찾았는데 어떻게 고쳐야할지는 잘 모르겠음(사실 4번 과정에서 포기하는 경우도 비일비재한데 어떻게든 스스로 해결하려 한 것만 해도 대단합니다.).

6. 꾸역꾸역 고쳐서 예제가 다 맞게 나오는 것을 확인한 후 제출했는데 틀림(맞왜틀..)

7. BOJ 질문 게시판에 내 코드에 대한 반례가 있는지 확인, 반례를 찾아내면 다시 6번으로

8. 이미 시간은 5시간 가까이 지나있고 모든 상황을 다 생각한 것 같은데 여전히 틀림. 정신적으로 지쳐 혼자 힘으로 해결하는건 포기하고 BOJ 질문 게시판에 반례를 찾아달라고 본인의 코드를 올림 

9. 답변을 기다리는 중에 검색을 통해 다른 사람의 코드를 확인해보지만 그냥 구현을 해냈구나 정도만 생각이 들고 크게 와닿는건 없음. 정말 운이 좋게 스파게티같은 나의 코드를 확인하고 반례를 찾아준 사람이 있다면 그 반례를 통해 코드를 바로잡음. 그렇지 않다면 사실상 이 문제는 버려진거고 먼 훗날에 다시 풀어보게 됨

 

이렇게 문제를 풀려고 시도는 하지만 별 소득없이 시간을 버리고, 발전이 없는 것 같아 좌절하는 일을 여러 번 겪다보면 도저히 공부를 할 마음이 안생겨 손 놓게 되는 상황이 많이 생길 것 같습니다. 

 

이 굴레를 벗어나기 위해서는 아무리 힘들어도 내가 짠 코드로 문제를 맞춰야합니다. 그 과정에서 가장 필요한건 내 코드를 인내심있게 확인한 후 잘못을 찾아줄 수 있는 사람입니다. 예제는 어느 정도 맞는데 실제로 제출했을 때에는 틀린다면 보통은 정말 간단한 실수 여러 개가 중첩되어서 코드가 저세상으로 가버린 경우입니다. 그렇기 때문에 혹시 주변 지인들 중에 알고리즘을 잘하는 사람이 있다면 매주 주말마다 소고기를 한 번씩 사주는 한이 있더라도 꼭 붙잡으세요. 거창하게 과외처럼 직접 만나서 뭔가를 할 필요는 없고 이틀에 한 번 정도라도 코드를 보냈을 때 대충 이 부분이 잘못된 것 같다고 찝어줄 수 있는 정도의 사람이 있다면 공부를 하는게 훨씬 편해집니다.

 

주변에 도저히 그런 지인이 없다면 카톡 오픈 채팅방이나 기타 온라인 커뮤니티를 이용해 도움을 요청할수도 있긴 하겠지만 이 경우에는 답변을 받을 확률이 좀 떨어집니다. 저도 가끔씩 BOJ 질문 게시판을 보면서 질문에 대해 답을 드리고 또 강의를 듣다가 본인의 틀린 코드를 보내주며 도움을 달라고 하시는 분들을 위해 코드의 틀린 점을 찾으려고 애쓸 때가 있지만 코드가 한 100줄을 넘어가고 수많은 ctrl+c ctrl+v로 인해 난장판이 되어버린 코드는 솔직히 읽어서 로직을 따라가는 것 부터가 상당히 힘듭니다. 그나마 답변받을 확률을 높이려면 일단 코드에 불필요한 부분을 날려 최대한 알아보기 쉽게 만들고 코드에 주석을 아주 상세하게 달고 어떤 로직으로 코드가 진행된건지를 별도의 글로 첨부하는게 좋습니다.

 

이렇게 지인이든 온라인 커뮤니티든 도움을 받을 수 있다면 베스트이지만 지인한테 매일같이 물어보기도 좀 미안하고 해서 어쩔땐 정말 혼자 힘으로 헤쳐나가야 하는 순간도 있습니다. 이 때에는 타인의 정답 코드를 참고해야 하는데, 타인의 정답 코드를 어떻게 보면 좋은지 2048 (Easy)를 예시로 들어 알아보겠습니다.

 

먼저 문제에서 내가 구현해야하는걸 잘게 쪼갭니다. 이 문제라면

 

1. 게임판을 상하좌우로 기울이기

2. 5번 기울이는 각각의 방향을 정하기

 

이 2가지가 됩니다. 1번은 전형적인 구현 문제이고 2번은 백트래킹 혹은 0부터 1023까지의 수를 4진법으로 변환하는 방법으로 해결할 수 있습니다.

 

모든 과정이 main에 다 들어있으면 너무 코드가 난잡해지니 1번, 2번 과정을 전부 함수로 빼두거나 적어도 1번 과정은 함수로 빠져있는게 좋을텐데 아마 본인이 짠 코드는 뒤죽박죽 엉켜서 엉망이 되어있을 수 있습니다. 인내심을 가지고 본인의 코드에서 1번 역할을 하는 코드와 2번 역할을 하는 코드를 분리합니다.

 

그리고 찾아낸 정답 코드를 살펴보며 그 안에서 1번 역할을 하는 코드와 2번 역할을 하는 코드가 어디있는지 확인합니다. 제대로 된 코드를 찾았다면 기능별로 알아보기 쉽게 구분이 잘 되어있을 것입니다. 정답 코드가 너무 알아보기 힘들면 다른 코드를 찾아보세요.

 

이제 이 상황에서 내가 게임판을 상하좌우로 기울이기 위해 구현한 방법과 정답 코드에서 구현한 방법을 비교해봅니다. 만약 방법이 똑같다면 내쪽에 구현 실수가 있는지 확인하는게 쉬울거고 다르다면 웬만해서는 정답 코드에서 구현한 방법이 더 효율적일테니 방법을 이해하고 습득합니다. 5번 기울이는 모든 상황을 테스트해보는 것도 비교해봅니다.

 

즉 핵심은 정답 코드를 기능 단위로 쪼개서 비교해보는 것입니다. 각 기능을 담당하는 코드는 보통은 30~40줄 안이기 때문에 100줄이 넘어가는 전체 코드를 들여다보면서 고민하는 것 보다는 훨씬 보기가 쉬울 것입니다. 이 과정에서 내가 문제를 잘못 이해했음을 깨닫거나 코드의 개선 방향이 눈에 들어올 수 있습니다. 설령 내 코드의 문제점을 찾지 못하더라도 정답 코드의 로직을 이해한다는 생각으로 정답 코드를 봅니다.

 

이 과정에서 본인 코드의 오류를 찾았다면 다행이고, 오류를 여전히 찾지 못했다면 다시 갈아엎고 짭니다. 정답 코드를 보고난 뒤이기 때문에 맨 땅에 헤딩할 때 보다는 구조적으로 개선된 형태의 코드가 나올겁니다. 갈아엎고 짜서 통과된다면 정말 다행이지만 다시 틀릴 수 있습니다. 이 때에는 또다시 정답 코드와 각 기능 단위의 코드를 비교해봅니다. 이 때에는 실제로 내 코드의 각 기능이 잘 동작하는지를 확인해볼 필요가 있습니다.

 

예를 들어

 

0 0 0 0

2 2 0 8

4 4 4 4

2 4 4 8

 

을 왼쪽으로 기울이면

 

0 0 0 0

4 8 0 0

8 8 0 0

2 8 8 0

 

이 잘 되는지, 또 5번 기울이는 모든 상황을 확인하는게 맞는지 등을 출력을 통해 확인해야 합니다.

 

여기까지 했으면 정말 운이 나쁜게 아니고서야 웬만하면 맞을겁니다. 만약 여기까지 했는데도 틀리고 꽉 막혀서 온 세상을 불살라버리고 싶은 기분이 든다면 저에게 코드를 보내주세요.. 도와드릴게요..

 

코딩테스트가 그렇게 쉽지는 않지만 주변의 여러 예시들을 볼 때 짧게는 2개월에서 길게는 4개월 정도 매진하시면 A형 정도의 수준에 도달할 수 있습니다(다만 코딩테스트가 단순한 1차 거름막인 경우가 아니라 카카오 블라인드 채용과 같이 변별력을 확실히 내겠다는 기조의 코딩테스트를 대비하기 위해서는 그래프 이론, 이분 탐색 등을 포함한 여러 알고리즘을 습득할 필요가 있습니다). 특히 이전에 코딩테스트 공부를 해보려다 좌절한 경험이 있는 분에게 제 글이 조금이나마 도움이 되면 좋겠습니다.

  Comments
  • 알린이
    멋있어요.
    역시 divide and conquer 이 진리죠
    기능별로 쪼개서 디버깅하면, 라인수는 길어질지 몰라도 이게 구현에서 실수할 가능성도 줄어들고 디버깅도 쉽더라구요.

    그리구 저는 제 코드스타일을 바꾸게 된 계기가 여러개 있지만 ,
    그중 하나가 백준 질문게시판에 있는 다른 사람 질문에 대해 대답하는걸 몇번 해보다 보니
    읽기 좋은 코드, 읽기 싫은 코드가 딱 눈에 들어오더라구요. 그래서 읽기 좋은 코드를 쓰는 연습이 좀 된거 같아요.
    ex ) 불필요한 들여쓰기 대신 continue 로 분기처리 / 한줄 if문 경우 , 중괄호를 열지 않고 바로 처리 등등..

    코테 준비하면서 단순히 PS적인 사고력, 능력만 늘어난게 아니고 전체적인 개발에 도움이 되는 역량도 많이 늘어난것 같아요.
  • ㅇㅇ
    혹시 소고기 좋아하시나요?
    자주 사드릴 수 있는데 ㅎㅎ
  • CCCC
    혹시 추천해주실만한 알고리즘 교재 있을까요?
    학부 2학년 정도의 수준입니다.
  • 올해안에취업
    실버문제까지는 잘구현이되는데, 100줄 이상 넘어가니까 집중력도 떨어지고, 가독성도 떨어져서 말씀하신대로 멘붕왔었는데 말씀하신대로 해봐야겠어요.. 아마 올해안에 가긴 그른거같네요 하하..

    잘읽고갑니다.
댓글 쓰기