일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 빅오메가
- solutions of matrix equation
- 코틀린 Hello World!
- homogeneous linear system
- matrix fo a linear transformation
- linear dependence
- one-to-one
- Big Theta
- recursive algorithms
- matrix-vector product
- NumPy
- Big-O 예제
- nontrivial solution
- Big-Oh notation
- 알고리즘 분석의 실례
- 이진 탐색
- 랜덤 순서 배열
- 일차변환
- nonhomogeneous linear system
- Big Omega
- matrix trnasformations
- itertools
- 빅오 표기법
- 코틀린 시작하기
- 빅세타
- 배열 섞기
- python
- trivial solution
- Big-Oh 예제
- 재귀함수
- Today
- Total
코딩 연습
하노이의 탑 본문
베트남의 수도 하노이에 있는 불교 사원에 전해지는 이야기 중 다음과 같은 것이 있다고 한다.
다이아몬드로 이루어진 3개의 기둥 중 하나에 64개의 황금 원반이 끼워져 있다. 황금 원반은 크기가 모두 다르며, 아래쪽에서 위쪽으로 갈수록 크기가 작아져서 전체적으로는 원뿔형의 탑을 이루고 있다. 이 64개의 원반을 한 번에 하나씩 움직여 모두 다른 쪽 기둥으로 옮기려고 한다. 단, 옮기는 과정에서 작은 원반 위에 큰 원반이 놓일 수는 없다. 이런식으로 원반들이 처음 있던 기둥에서 다른 기둥으로 모두 옮겨지면 세상이 끝난다는 전설이 있다.
하노이의 탑 문제는 유명하기 때문에 여기까지 검색해서 오신 분들이라면 다른 설명이 필요 없을 것이라고 생각된다.
이 문제는 재귀함수를 이용하여 간단하게 해결할 수 있다. (물론 이해하고 나면 간단하지만, 이해하기 전에는 무지하게 복잡하다.)
편의상 기둥에 번호를 붙여 1번 기둥, 2번 기둥, 3번 기둥이라고 부르자.
1번 기둥에 $n$ 개의 원반이 쌓여 있고, 모두 2번 기둥으로 옮기려고 하면 다음과 같은 과정을 거치면 된다.
i) 1번 기둥에서 가장 밑 원반을 제외한 $n-1$ 개의 원반을 3번 기둥으로 옮긴다.
ii) 1번 기둥에 남은 가장 큰 원반을 2번 기둥으로 옮긴다.
iii) 3번 기둥에 있는 $n-1$ 개의 원반을 2번 기둥으로 옮긴다.
4개의 원반이 있다고 하면 위 과정을 다음과 같이 나타낼 수 있다.
이런 과정을 Go 언어로 표현하면 다음과 같다.
package main
import "fmt"
func hanoi(n, a, b int) {
if n == 1 {
fmt.Printf("%d -> %d\n", a, b)
} else {
c := 6 - a - b
hanoi(n - 1, a, c)
hanoi(1, a, b)
hanoi(n - 1, c, b)
}
}
func main() {
var num int
fmt.Println("Number of disks: ")
fmt.Scanln(&num)
hanoi(num, 1, 2)
}
C 언어로 나타내면 다음과 같다.
#include<stdio.h>
void hanoi(int n, int a, int b) {
int c;
if (n == 1) {
printf("%d -> %d\n", a, b);
} else {
c = 6 - a - b;
hanoi(n - 1, a, c);
hanoi(1, a, b);
hanoi(n - 1, c, b);
}
}
int main(void) {
int num;
printf("Input number of disks : ");
scanf("%d", &num);
hanoi(num, 1, 2);
return 0;
}
a 는 출발지(처음 원반들이 꽂혀 있던 기둥), b 는 도착지(원반들을 옮기고자 하는 기둥), c 는 경유지(원반들이 거쳐가는 기둥) 으로 이해하면 될 것이다. 아마 위 과정과 코드를 같이 보면 충분히 이해가 가리라 생각된다.
결과는 다음과 같다.
Number of disks: 3
1 -> 2
1 -> 3
2 -> 3
1 -> 2
3 -> 1
3 -> 2
1 -> 2
위 출력 결과에서 "1 -> 2" 라는 것은 "1 번 기둥의 맨 위쪽 원반을 2번 기둥으로 옮긴다." 를 나타낸다. 원반이 3개 인 경우는 위와 같이 이동 횟수가 총 7번이 되어야 한다.
'알고리즘' 카테고리의 다른 글
(재귀함수) $n!$ ($n$ 의 계승) 구하기 (0) | 2017.04.29 |
---|---|
(재귀함수) 자(ruler)의 눈금 그리기 (1) | 2017.04.29 |
N-queens 문제 (0) | 2016.03.31 |
달팽이 배열 (5) | 2016.03.29 |
예제로 알아보는 확장 유클리드 알고리즘 (0) | 2016.03.17 |