edubun English

알고리즘이란

약 2,300년 전에 쓰인 유클리드 『원론』 7권의 최대공약수 구하는 방법은 지금도 컴퓨터 안에서 돌아갑니다.

언제나 통하는 방법

1071과 462를 둘 다 나누어떨어지게 하는 가장 큰 수를 구해야 한다고 해 봅시다. 462부터 1까지 하나씩 나눠 보고 둘 다 나누어떨어지는 첫 수에서 멈출 수도 있습니다. 답은 나오지만 수백 번을 시도해야 할 수도 있습니다. 더 짧은 길이 있습니다. 1071을 462로 나눈 나머지 147을 남깁니다. 이번에는 462를 147로 나눈 나머지 21을 남깁니다. 147을 21로 나누면 나머지가 0이므로 답은 21입니다. 수백 번 대신 나눗셈 세 번이면 됩니다.

이 짧은 길이 알고리즘입니다. 알고리즘은 어떤 입력을 받아 올바른 출력을 내는, 유한한 개수의 정확한 단계 목록입니다. 위의 방법은 최대공약수를 구하는 유클리드 알고리즘으로, 기원전 300년 무렵에 쓰인 『원론』 7권에 나옵니다. 유클리드는 나눗셈 대신 큰 수에서 작은 수를 거듭 빼는 방식으로 설명했지만 생각은 같고, 나머지를 쓰는 방식이 오늘날 프로그램에서 쓰는 형태입니다.

function gcd(a, b) {
  while (b !== 0) {
    const r = a % b;   // remainder
    a = b;
    b = r;
  }
  return a;
}
console.log(gcd(1071, 462)); // 21

단계 목록이 알고리즘이 되는 조건

코먼, 레이서슨, 리베스트, 스타인의 교과서 같은 책은 알고리즘을 입력을 출력으로 바꾸는 잘 정의된 절차라고 설명합니다. 이 설명에는 세 가지가 들어 있고, 코드를 쓸 때 하나하나가 중요합니다.

  • 정확함. 단계마다 뜻이 하나입니다. 「a를 b로 나누고 나머지를 남긴다」는 정확하지만 「어떻게든 수를 작게 만든다」는 그렇지 않습니다.
  • 유한함. 반드시 멈춰야 합니다. 유클리드 알고리즘에서 나머지는 늘 나눈 수보다 작으므로 단계마다 줄어들고, 결국 0에 닿습니다.
  • 올바름. 시험해 본 예만이 아니라 허용된 모든 입력에 대해 맞는 답을 냅니다.

요리법이 흔한 예로 쓰이는데, 꽤 맞는 비유입니다. 재료가 입력, 음식이 출력이고 단계에 순서가 있습니다. 차이는 읽는 쪽이 얼마나 채워 넣느냐입니다. 요리사는 「한 꼬집」이 얼마인지 스스로 정합니다. 컴퓨터는 아무것도 정하지 않으므로 컴퓨터용 알고리즘은 모든 단계를 빠짐없이 적습니다.

같은 문제, 다른 알고리즘

문제 하나에는 보통 올바른 알고리즘이 여러 개 있고, 하는 일의 양은 크게 다를 수 있습니다. 1071과 462의 최대공약수를 462부터 하나씩 내려가며 찾으면 21에 닿기까지 442번을 시도해야 하지만, 유클리드 방법은 나눗셈 3번이면 됩니다. 둘 다 맞습니다. 빠른 것은 하나뿐입니다. 이 과정의 상당 부분이 이 두 번째 질문을 다룹니다. 방법이 맞다면, 몇 단계가 걸리고, 입력이 커질 때 그 수가 어떻게 늘어날까요?

이 질문에 답할 때 컴퓨터 과학자는 초 대신 기본 단계(비교 한 번, 교환 한 번, 나눗셈 한 번)를 셉니다. 걸리는 초는 기계에 따라 다르지만, 단계 수는 알고리즘과 입력에만 달려 있어서 두 방법을 공정하게 비교할 수 있습니다. 아래 실험실은 막대를 정렬하면서 비교 횟수를 세어 줍니다. 같은 처음 순서로 두 방법을 돌려 보고 숫자를 비교해 보세요.

불러오는 중

끌어서 돌리고, 휠이나 두 손가락으로 확대하세요.

같은 값 여덟 개를 선택 정렬과 삽입 정렬로 정렬합니다. 숫자는 각 방법이 비교와 교환을 몇 번 했는지 보여 줍니다.

입력, 출력, 그 사이의 단계

알고리즘을 쓰기 전에 무엇이 들어가고 무엇이 나와야 하는지부터 정확히 적습니다. 최대공약수라면 입력은 양의 정수 두 개이고, 출력은 둘을 모두 나누어떨어지게 하면서 그보다 큰 수는 그렇지 못한 정수 하나입니다. 이렇게 적어 두면 결과를 어떻게 확인할지 알 수 있고, 단계의 실마리가 보이기도 합니다. 경계에 있는 경우도 드러납니다. 한쪽 수가 0이면 어떻게 될까요? (위의 반복문은 다른 쪽 수를 돌려주는데, 그것이 맞는 답입니다.) 두 수가 같으면 어떨까요? 코드를 돌리기 전에 이런 경우를 생각해 두면 많은 실수를 미리 잡습니다.

배경알고리즘이라는 말은 사람 이름에서 왔습니다. 무함마드 이븐 무사 알콰리즈미는 9세기 바그다드에서 활동했고, 0부터 9까지의 인도 숫자로 계산하는 법을 책으로 썼습니다. 이 책의 라틴어 번역은 「Dixit algorizmi」(알콰리즈미가 말하기를)라는 말로 시작하고, 흔히 「Algoritmi de numero Indorum」이라는 제목으로 불립니다. 그의 이름을 라틴어로 적은 algorizmi, algoritmi가 단계별 계산 방법을 뜻하는 낱말이 되었습니다. 방정식 푸는 법을 다룬 그의 다른 책에서는 대수학(algebra)이라는 낱말이 나왔습니다. 한참 뒤인 1843년, 에이다 러브레이스는 찰스 배비지가 설계만 하고 만들지 못한 해석기관에 관한 주석을 발표했습니다. 그 마지막인 주석 G에는 이 기계가 베르누이 수를 계산하는 과정이 단계별로 적혀 있습니다.
  • 기원전 300년 무렵: 유클리드 『원론』 7권: 최대공약수 구하는 방법.
  • 9세기: 바그다드의 알콰리즈미가 인도 숫자 계산법을 씁니다. 그의 라틴어 이름에서 알고리즘이라는 말이 나옵니다.
  • 1843: 에이다 러브레이스의 주석 G: 해석기관이 베르누이 수를 계산하는 단계.
  • 1945: 존 폰 노이만이 병합 정렬을 제안합니다.
  • 1959: 토니 호어가 모스크바에서 퀵 정렬을 고안합니다(1961년 발표).
알고리즘입력을 올바른 출력으로 바꾸는 유한한 개수의 정확한 단계 목록
입력알고리즘이 처음 받는 데이터
출력알고리즘이 내야 하는 결과
올바름허용된 모든 입력에 맞는 출력을 냄
유한함몇 단계 뒤에는 반드시 멈춤
최대공약수두 수를 모두 나누어떨어지게 하는 가장 큰 정수
경계 사례0, 빈 목록, 같은 값처럼 흔하지 않은 입력
단계 수알고리즘이 하는 기본 연산의 횟수
  1. 유클리드 알고리즘으로 48과 18의 최대공약수를 구하세요.
  2. 1071과 462에 유클리드 알고리즘을 쓰면 나눗셈을 몇 번 할까요?
  3. 모든 알고리즘이 갖춰야 하는 성질이 아닌 것은?
    • 유한한 단계 뒤에 멈춤
    • 단계마다 뜻이 정확함
    • 컴퓨터를 씀
    • 허용된 모든 입력에 맞는 답을 냄
  4. 유클리드 알고리즘이 언제나 멈추는 이유는?
    • 나머지는 늘 나눈 수보다 작아서 0까지 줄어들기 때문
    • 10번 돌면 멈추기 때문
    • 컴퓨터가 반복문을 알아서 멈추기 때문
    • 두 수가 같아질 때까지 커지기 때문
  5. 알고리즘이라는 낱말은 누구의 이름에서 왔을까요?
    • 유클리드
    • 알콰리즈미
    • 에이다 러브레이스
    • 앨런 튜링
  6. 컴퓨터 과학자가 초 대신 단계 수를 세는 이유는?
    • 초는 기계마다 다르지만 단계 수는 알고리즘과 입력에만 달려 있어서
    • 시계가 부정확해서
    • 단계가 늘 더 빨라서
    • 코드로 초를 잴 수 없어서
  7. 시험해 본 예 다섯 개에서 맞는 답이 나왔습니다. 이 방법은 올바를까요?
    • 예, 다섯 개면 증명됩니다
    • 꼭 그렇지는 않습니다. 허용된 모든 입력에서 맞아야 합니다
    • 빠를 때만
    • 반복문을 쓸 때만
  8. 이 단원의 반복문으로 gcd(35, 0)을 계산하면 무엇이 나올까요?
  9. 에이다 러브레이스가 주석 G를 포함한 주석을 발표한 해는?
    • 1801년
    • 1843년
    • 1945년
    • 1961년
  10. 유클리드 알고리즘의 단계를 순서대로 놓으세요.
핵심 정리
  • 알고리즘은 입력에서 올바른 출력까지 가는 유한한 개수의 정확한 단계 목록입니다.
  • 유클리드 알고리즘은 나머지를 거듭 구해 최대공약수를 찾습니다.
  • 한 문제에 올바른 알고리즘이 여럿 있을 수 있고, 단계 수는 크게 다를 수 있습니다.
  • 단계를 쓰기 전에 입력, 출력, 경계 사례부터 적습니다.
  • 알고리즘이라는 말은 알콰리즈미의 라틴어 이름에서 왔습니다.