일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- backtracking
- OS
- DP
- 자바
- 모던자바
- 백트래킹
- back-end
- 백준
- Spring
- 스프링
- 그래프
- BFS
- 운영체제
- java
- baekjoon
- 코틀린
- Brute-force
- Java8
- LEVEL2
- TDD
- 자료구조
- DFS
- algorithm
- kotlin
- 네트워크
- 프로그래머스
- lambda
- 프로젝트
- 알고리즘
- programmers
- Today
- Total
요깨비's LAB
[백준, BackTracking, Kotlin] P.2580 스도쿠 본문
import java.util.*
var isComplete = false
class ZeroArea(
var row: Int,
var col: Int,
var visited: Array<Boolean> = Array(9) { false }
)
val map = Array<Array<Int>>(9) {
Array<Int>(9) {
0
}
}
fun main() {
val scr = Scanner(System.`in`)
val zeroAreas = mutableListOf<ZeroArea>()
for (i in 0 until 9) {
for (j in 0 until 9) {
map[i][j] = scr.nextInt()
if (map[i][j] == 0) {
zeroAreas.add(ZeroArea(i, j))
}
}
}
for (zeroArea in zeroAreas) {
checkRow(zeroArea)
checkCol(zeroArea)
checkSquare(zeroArea)
}
val zeroAreasSize = zeroAreas.size
makeSudoku(zeroAreas, 0, zeroAreasSize)
printlnResult()
}
fun printlnResult() {
for (i in 0 until 9) {
for (j in 0 until 9) {
print("${map[i][j]} ")
}
println()
}
}
fun checkRow(element: ZeroArea) {
for (i in 0..8) {
if (map[i][element.col] != 0) {
element.visited[map[i][element.col] - 1] = true
}
}
}
fun checkCol(element: ZeroArea) {
for (i in 0..8) {
if (map[element.row][i] != 0) {
element.visited[map[element.row][i] - 1] = true
}
}
}
fun checkSquare(element: ZeroArea) {
val r = if (element.row in 0..2) {
0
} else if (element.row in 3..5) {
3
} else if (element.row in 6..8) {
6
} else {
-1
}
val c = if (element.col in 0..2) {
0
} else if (element.col in 3..5) {
3
} else if (element.col in 6..8) {
6
} else {
-1
}
for (i in 0..2) {
for (j in 0..2) {
if (map[r + i][c + j] != 0) {
element.visited[map[r + i][c + j] - 1] = true
}
}
}
}
fun checkValidRow(element: ZeroArea, value: Int): Boolean {
for (i in 0..8) {
if (map[i][element.col] == value) {
return false
}
}
return true
}
fun checkValidCol(element: ZeroArea, value: Int): Boolean {
for (i in 0..8) {
if (map[element.row][i] == value) {
return false
}
}
return true
}
fun checkValidSquare(element: ZeroArea, value: Int): Boolean {
val r = when (element.row) {
in 0..2 -> {
0
}
in 3..5 -> {
3
}
in 6..8 -> {
6
}
else -> {
-1
}
}
val c = when (element.col) {
in 0..2 -> {
0
}
in 3..5 -> {
3
}
in 6..8 -> {
6
}
else -> {
-1
}
}
for (i in 0..2) {
for (j in 0..2) {
if (map[r + i][c + j] == value) {
return false
}
}
}
return true
}
fun makeSudoku(zeroAreas: MutableList<ZeroArea>, index: Int, zeroAreasSize: Int) {
if (index >= zeroAreasSize) {
isComplete = true
return
}
val zeroArea = zeroAreas[index]
for (i in 0..8) {
if (!zeroArea.visited[i]) {
if (checkValidCol(zeroArea, i + 1) && checkValidRow(zeroArea, i + 1) && checkValidSquare(zeroArea, i + 1)) {
map[zeroArea.row][zeroArea.col] = i + 1
makeSudoku(zeroAreas, index + 1, zeroAreasSize)
if (isComplete) {
return
} else {
map[zeroArea.row][zeroArea.col] = 0
}
}
}
}
}
1) 9 X 9의 2차원 배열에 스도쿠 값을 입력받으면서 0 값일 경우 zeroAreas라는 리스트에 빈 값에 대한 객체를 만들어 저장합니다.
2) zeroAreas를 순회하면서 행, 열, 3X3 영역을 체크하여 정답이 될 수 있는 값들을 추려냅니다.
3) 추려낸 값들을 기반으로 스도쿠를 만들어 나갑니다.
3-1) zeroAreas의 0번째 인덱스 부터 시작하며 인덱스가 zeroAreas의 크기와 같거나 크면 스도쿠를 완성한 것이므로
완성 상태를 알리기 위한 isComplete를 true로 업데이트 하고 리턴합니다.
3-2) 3-1를 충족하지 않을 경우,
<1> zeroArea의 값이 될 수 있는 visited를 순회하면서 아직 방문하지 않은(스도쿠 안의 내용을 채울 수 있는) index일 경우,
행, 열, 3X3영역 체크를 통해 해당 위치에 해당 값이 스도쿠를 만들기에 적합한 값인지 검증합니다.
<2> 적합한 값일 경우 map의 해당 위치에 값으로 업데이트를 하고 다음 인덱스로 makeSudoku를 재귀로 다시 진입합니다.
<3> makeSudoku를 끝낸 후에 isComplete 상태 값을 확인하여 true일 경우, 스도쿠 완성이 된 것이므로 return으로 종료합니다.
false일 경우, 스도쿠 완성이 되지 않았으며 해당 값으로는 스도쿠를 완성할 수 없기에, <2>에서 수정한 map을 0값으로 되돌립니다.
그 후, for문의 다음 i값으로 연산을 진행합니다.
위의 과정을 반복하면 원하는 스도쿠를 만들어 낼 수 있습니다.
10번 정도 틀리고 시행 착오를 겪으면서 풀었습니다... 그래도 이번에는 오랜만에 구글링의 도움을 받지 않고 풀었던것 같아
뿌듯합니다. 혹시 중간에 불필요한 연산이 있다면 알려주시면 감사하겠습니다.
'알고리즘(Kotlin) > Back-Tracking' 카테고리의 다른 글
[백준, Back-Tracking, Kotlin] P.4344 평균은 넘겠지 (0) | 2021.04.08 |
---|---|
[백준, BackTracking, Kotlin] P.16198 에너지 모으기 (0) | 2021.04.08 |
[백준, BackTracking, Kotlin] P.15658 연산자 끼워넣기2 (0) | 2021.04.06 |
[백준, BackTracking, Kotlin] P.2529 부등호 (0) | 2021.04.06 |
[백준, BackTracking, Kotlin] P.15650 N과 M (0) | 2021.03.24 |