카테고리 없음

Merge sort 때문에 시험을 망쳤다.

falto 2025. 11. 25. 19:45

C언어로 코딩하는 시험이었다. 과거 첫 번째 시험과 두 번째 시험 모두 100점을 받았기에, 세 번째 시험을 위해 별 준비를 안 해도 무리 없이 다 풀 수 있을 거라고 생각했다. 교수님이 정렬 알고리듬 구현이 필요하다고 말했지만 미래의 내가 백준으로 단련한 실력으로 알아서 어떻게든 하겠지 하고 준비를 안 했다. 이때 준비를 했어야 했는데... 그냥 강의 자료에 파일 입출력만 대충 훑어보고 자버렸다.

 

시험 시간은 약 2시간 30분 정도 주어졌다. 시험이 시작하고 문제지를 보니 문제는 총 세 문제였다. 어쩐지 오늘따라 머리가 좀 어지러운 것 같았다. 잠을 너무 늦게 잤나. 첫 문제는 구현하기 약간 까다로워서 건너뛰었다. 나중에 시간 남을 때 다시 돌아올 셈이었다.

 

두 번째 문제는 정렬이 필요한 문제였다. 문제에 시간 제한이나 시간 복잡도 제한은 없으니 정렬 알고리듬이 N log N에 돌든 제곱 시간에 돌든 점수에는 아무런 지장이 없었다. 하지만 나는 괜히 여유를 부리겠다고 더 효율적인 N log N에 도는 merge sort를 구현하려고 했다. 그런데 예상치 못한 버그가 자꾸 발생하면서 시간이 사르르 녹아내렸다. void 포인터 스왑하는 방법도 몰라서 typedef로 온몸비틀기하고, printf로 디버깅하고... 그러다 시간이 얼마 안 남아서 결국 merge sort를 중간에 폐기하고 제곱 시간에 도는 selection sort를 급하게 구현했다. selection sort도 여러 번 디버깅하면서 겨우겨우 완성했다. 그 쉽고 직관적인 selection sort를 구현할 때도 어이 없는 실수를 자꾸만 했다. i를 넣어야 하는 곳에 0을 넣는다든가, i와 j를 혼동한다든가 하는 것들 말이다. Selection sort도 제대로 구현 못 하는 정신 상태로 merge sort를 구현하려 했으니 될 리가 없었다. 결국 merge sort 하나 때문에 시험 시간의 반을 넘게 날려먹고 성공적으로 구현하지도 못 했다. 시간이 다 되어서 첫 문제와 마지막 문제는 반도 못 풀고, 두 번째 문제만 완벽하게 풀어서 마감했다.

 

시험 결과를 예상해보건대 아마 이번에는 반 평균 미만의 점수가 나올 것 같다. 하필 이번 시험에는 교수가 학생들의 부정행위 방지를 위해 시험 시작 때 자리를 바꾸도록 시켰는데, 그걸 시키고 나서 내 점수가 뚝 떨어졌을테니... 설마 교수가 날 부정행위로 100점 맞아온 학생으로 오해하진 않겠지?

 

그냥 아래 코드처럼 간단하게 구현할 걸 그랬다. 참고로 아래 C 소스 코드에 쓰인 정렬 알고리듬은 https://arxiv.org/abs/2110.01111

 

Is this the simplest (and most surprising) sorting algorithm ever?

We present an extremely simple sorting algorithm. It may look like it is obviously wrong, but we prove that it is in fact correct. We compare it with other simple sorting algorithms, and analyse some of its curious properties.

arxiv.org

여기 논문에 나온 알고리듬이다. 증명은 안 읽어봤지만 해보니까 정말 정렬이 되더라.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>


typedef struct _person{
	char name[99];
	int age;
	char sex;
}person;



// Source - https://stackoverflow.com/a/29596215
// Posted by Kerrek SB, modified by community. See post 'Timeline' for change history
// Retrieved 2025-11-25, License - CC BY-SA 3.0

void swap(void * a, void * b, size_t len)
{
    unsigned char *p=a, *q=b, tmp;
    for (size_t i = 0; i != len; ++i)
    {
        tmp = p[i];
        p[i] = q[i];
        q[i] = tmp;
    }
}


void sort(void*ptr,size_t count,size_t size, int (*comp)(const void*,const void*)){
	for(size_t i=0;i<count;i++)
	for(size_t j=0;j<count;j++)
	if(comp(ptr+i*size,ptr+j*size)<0)
	swap(ptr+i*size,ptr+j*size,size);
}


int cmp(const void*x,const void*y){
	return strcmp(((person*)x)->name,((person*)y)->name);
}


int main(){
	person people[3]={{"John",20,'M'},{"Bob",21,'F'},{"Kate",19,'M'}};
	sort(people,3,sizeof(person),cmp);
	for(int i=0;i<3;i++){
		printf("%s ",people[i].name);
	}
	return 0;
}

 

 

그래서 이번 일로 얻은 교훈은 무엇이나.

1. 자만하지 말자. 점수를 얻기 위해 최선을 다하자.

2. 프로그램은 이상한 거 신경쓰지 말고 요구 사항에만 맞춰서 작성하자. 프로그램의 실행 시간보다 더 중요한 것은 프로그래머의 개발 시간이다.

3. 유비무환. 준비를 빈틈없이 단단히 하자.

 

시험 전날 merge sort 구현 연습을 했으면 시험을 망칠 일이 없었을 것이고, 연습을 안 했다 하더라도 시험 중에 처음부터 selection sort 구현으로 방향을 잡았다면 이렇게까지 망하진 않았을 텐데. 많이 아쉽다. 시험이 끝난 직후 충격을 많이 먹었다. 시험 끝나고나서 점심 먹고 노트북으로 merge sort 구현을 하고 돌려봤는데 아주 얄밉게도 잘 되더라. 시험 때는 대체 뭐가 문제였던 거지.