일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- JPA
- python3
- 스프링부트
- 장고
- 자료구조
- 스프링
- django
- 스프링 부트
- 데이터베이스
- 파이썬3
- 자바
- java
- 보안
- Spring
- 파이썬
- rabbitmq
- 개발
- 안드로이드
- db
- 디자인 패턴
- 웹
- mysql
- bytecode
- 웹 개발
- node.js
- Spring Boot
- ORM
- HTTP
- Python
- BCI
- Today
- Total
semtax의 개발 일지
파이썬과 백트래킹 알고리즘을 이용한 스도쿠 구현 본문
개요
이번 시간에는 백 트래킹 알고리즘에 대해서 알아보도록 하겠습니다.
또한, 백 트래킹 알고리즘을 이용해서 스도쿠 퍼즐을 만드는 프로그램을 작성 해보도록 하겠습니다.
백 트래킹(Back Tracking)?
백 트래킹(Back Tracking)은 단어 뜻 그대로, 되 추적이라는 다시 되돌아가서 되돌아간 자리에서 시작한다는 말입니다.
어릴 적에 "경우의 수" 문제나, "확률과 통계" 문제를 풀 때를 떠올려 봅시다.
문제를 맨 처음 풀 때, 우리는 종이에 수형도 라고 부르는 나뭇가지를 처음부터 하나씩 그려서 갯수를 전부 세었습니다.
아니면, 길 찾기 문제를 풀 때 에도, 종이에 거의 모든 경우의 수를 그려서 직접 세서 풀었던 것을 기억 하실겁니다.
사실은 모든 경우의 수를 전부 세서 그렸다고 생각을 하고는 있지만,
실제로는 문제에서 절대로 안될것 같은 부분을 마주쳤을때, 그 부분은 제외하고(즉, 가지치기를 하고)
다시 수형도를 그렸던 것을 떠올리실 수 있습니다.
이러한 방식을 백 트래킹(Back Tracking) 이라고 합니다.
여기서 핵심은 절대로 안될것 같은 부분을 가지치기 하는것입니다.
이를 통해, 일반적인 무식하게 모든 경우의 수를 다 해보는 알고리즘과는 다르게 꽤 많은 불필요한 중복 탐색을 제거합니다.
따라서, 상대적으로 모든 경우의 수를 무식하게 다 하는 경우 보다는 빠릅니다.
보통 백트래킹을 이용해서 N-Queen 문제나, 스도쿠 퍼즐 과 같은 문제를 풀 수 있습니다.
이번 포스팅에서는 백 트래킹 예제로, 파이썬으로 스도쿠 퍼즐을 생성하는 예제를 구현 할 것입니다.
백 트래킹을 이용한 스도쿠(Sudoku) 생성 프로그램 구현
해당 예제에서는, 가지치기 방식으로, 각 행/열, 및 3*3 사각형에,
1~9 까지의 숫자가 단 1개씩만 들어있는지를 체크 하는 방식으로 가지치기를 구현하게 됩니다.
이를 위해, row,col,diag 라는 2차원 리스트를 생성하였고,
이를 통해 각 행/열 및 3*3 사각형에 어떤 숫자가 들어있는지를 바로 파악 할 수가 있게 됩니다.
아래는 파이썬으로 백 트래킹 알고리즘을 이용 해서, 스도쿠 퍼즐을 생성 하는 프로그램을 구현한 코드 입니다.
import random
origin_board = [[0 for j in range(0,9)] for i in range(0,9)]
board = [[0 for j in range(0,9)] for i in range(0,9)]
row = [[0 for j in range(0,10)] for i in range(0,10)]
col = [[0 for j in range(0,10)] for i in range(0,10)]
diag = [[0 for j in range(0,10)] for i in range(0,10)]
terminate_flag = False
def board_init():
seq_diag = [0,4,8]
for offset in range(0,9,3):
seq = [i for i in range(1,10)]
random.shuffle(seq)
for idx in range(0,9):
i,j = idx//3,idx%3
row[offset+i][seq[idx]] = 1
col[offset+j][seq[idx]] = 1
k = seq_diag[offset//3]
diag[k][seq[idx]] = 1
origin_board[offset+i][offset+j] = seq[idx]
def make_sudoku(k):
global terminate_flag
global board
if terminate_flag == True:
return True
if k > 80:
for i in range(0,9):
for j in range(0,9):
board[i][j] = origin_board[i][j]
terminate_flag = True
return True
i,j = k//9,k%9
start_num = random.randint(1,9)
if origin_board[i][j] != 0:
make_sudoku(k+1)
for m in range(1,10):
m = 1 + (m + start_num)%9
d = (i//3)*3 + (j//3)
if row[i][m] == 0 and col[j][m] == 0 and diag[d][m] == 0:
row[i][m],col[j][m],diag[d][m] = 1,1,1
origin_board[i][j] = m
make_sudoku(k+1)
row[i][m],col[j][m],diag[d][m] = 0,0,0
origin_board[i][j] = 0
board_init()
make_sudoku(0)
for i in range(0,9):
print(board[i])
출력 결과는 아래와 같습니다.
(생성 때마다, 결과가 달라 집니다.)
[5, 1, 6, 7, 3, 9, 4, 2, 8]
[4, 2, 9, 8, 1, 5, 7, 6, 3]
[7, 8, 3, 4, 6, 2, 1, 9, 5]
[8, 4, 1, 6, 2, 7, 3, 5, 9]
[6, 5, 7, 3, 9, 4, 2, 8, 1]
[9, 3, 2, 1, 5, 8, 6, 4, 7]
[3, 6, 4, 5, 8, 1, 9, 7, 2]
[2, 7, 8, 9, 4, 3, 5, 1, 6]
[1, 9, 5, 2, 7, 6, 8, 3, 4]
'개발 > 알고리즘' 카테고리의 다른 글
위치정보를 빠르게 검색하자 : Geohashing (0) | 2021.01.10 |
---|---|
백분위수를 빠르고 효율적으로 계산하자 : DD-Sketch (0) | 2020.10.17 |
통계값을 효율적으로 저장하기 : HdrHistogram (0) | 2020.05.16 |
자료구조에서 그래프를 모델링하는 방법들 (0) | 2020.03.06 |
온라인 알고리즘을 이용해서 평균 값 구하기 (0) | 2020.02.23 |