Home 백준 - 2447 별 찍기 - 10
Post
Cancel

백준 - 2447 별 찍기 - 10

문제

2447 별 찍기 - 10

screencaptures

note

  • 분할 정복, 재귀를 사용하는 문제이지만, 분할 정복, 재귀를 사용하지 않고도 풀린다.

1. kotlin code: 분할 정복, 재귀를 사용하지 않는 코드

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
32
33
34
35
36
import kotlin.math.pow

fun main() {
    val input = readln().toInt()
    val stars = getStars(input)
    val output = getOutputString(stars)
    println(output)
}

private fun getStars(input: Int): Array<CharArray> {
    val stars = Array(input) { CharArray(input) { '*' } }
    val log3 = log(input, 3)
    for (l in (0 until log3)) {
        val blockSize = 3.0.pow(l).toInt()
        val to = input - blockSize
        for (y in (blockSize until to)) {
            val blankRow = (y / blockSize % 3) == 1
            for (x in (blockSize until to)) {
                val blankColumn = (x / blockSize % 3) == 1
                if (blankRow && blankColumn) stars[x][y] = ' '
            }
        }
    }
    return stars
}

private fun log(x: Int, base: Int):Int = (kotlin.math.log10(x.toDouble()) / kotlin.math.log10(3.0)).toInt()

private fun getOutputString(stars: Array<CharArray>): StringBuilder {
    val output = StringBuilder()
    for (row in stars) {
        for (column in row) output.append(column)
        output.append('\n')
    }
    return output
}
  • Q. 왜 log(input.toDouble(), 3.0)이 아닌, log10(input.toDouble()) / log10(3.0)을 사용할까?
  • A. kotlin.math.log(243.0, 3.0)이 5가 아닌 4.9999…가 결과로 나오기 때문이다.

2. kotlin code: 반환 값이 있는 재귀를 사용하는 코드

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
32
33
34
35
36
37
38
fun main() {
    val input = readln().toInt()
    val stars = getStars(input)
    val output = getOutputString(stars)
    println(output)
}

private fun getStars(n: Int): Array<CharArray> = when(n) {
    1 -> Array(1) { CharArray(1) {'*'} }
    else -> {
        val output = Array(n) { CharArray(n) {' '} }
        val block = n / 3
        for(y in (0..2)) {
            for(x in (0..2)) {
                if(y == 1 && x == 1) continue
                output.setStar(x*block, y*block, getStars(block))
            }
        }
        output
    }
}

private fun Array<CharArray>.setStar(x: Int, y: Int, starPattern: Array<CharArray>) {
    for ((py, row) in starPattern.withIndex()) {
        for ((px, column) in row.withIndex()) {
            this[py + y][px + x] = column
        }
    }
}

private fun getOutputString(stars: Array<CharArray>): StringBuilder {
    val output = StringBuilder()
    for (row in stars) {
        for (column in row) output.append(column)
        output.append('\n')
    }
    return output
}

3. kotlin code: 반환 값이 있는 재귀 + 캐시를 사용하는 코드

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
32
33
34
35
36
37
38
39
40
41
fun main() {
    val input = readln().toInt()
    val cache = hashMapOf(1 to Array(1) { CharArray(1) {'*'} })
    val stars = getStars(input, cache)
    val output = getOutputString(stars)
    println(output)
}

private fun getStars(n: Int, cache: MutableMap<Int, Array<CharArray>>): Array<CharArray> = when {
    cache.containsKey(n) -> cache[n]!!
    else -> {
        val output = Array(n) { CharArray(n) { ' ' } }
        val block = n / 3
        for (y in (0..2)) {
            for (x in (0..2)) {
                if (y == 1 && x == 1) continue
                val stars = getStars(block, cache)
                cache[block] = stars
                output.setStar(x * block, y * block, cache[block]!!)
            }
        }
        output
    }
}

private fun Array<CharArray>.setStar(x: Int, y: Int, starPattern: Array<CharArray>) {
    for ((py, row) in starPattern.withIndex()) {
        for ((px, column) in row.withIndex()) {
            this[py + y][px + x] = column
        }
    }
}

private fun getOutputString(stars: Array<CharArray>): StringBuilder {
    val output = StringBuilder()
    for (row in stars) {
        for (column in row) output.append(column)
        output.append('\n')
    }
    return output
}

4. kotlin code: 반환 값이 없는 재귀를 사용하는 코드(추천)

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
fun main() {
    val input = readln().toInt()
    val output = Array(input) { CharArray(input) {' '} }
    drawStars(0, 0, input, output)
    val outputString = getOutputString(output)
    println(outputString)
}

private fun drawStars(x:Int, y:Int, n: Int, output: Array<CharArray>): Unit = when(n) {
    1 -> output[x][y] = '*'
    else -> {
        val block = n / 3
        for(y2 in (0..2)) {
            for(x2 in (0..2)) {
                if(x2 == 1 && y2 == 1) continue
                drawStars(x + x2*block, y + y2*block, block, output)
            }
        }
    }
}

private fun getOutputString(stars: Array<CharArray>): StringBuilder {
    val output = StringBuilder()
    for (row in stars) {
        for (column in row) output.append(column)
        output.append('\n')
    }
    return output
}
This post is licensed under CC BY 4.0 by the author.

백준 - 11729 하노이 탑 이동 순서 풀이

백준 - 24444 알고리즘 수업 - 너비 우선 탐색 1