์ ๋ต์ฝ๋
import kotlin.test.*
import kotlin.time.*
enum class Direction {
`0`{
override fun x(x: Int, y: Int, size : Int) = x
override fun y(x: Int, y: Int, size : Int) = y
}, `90`{
override fun x(x: Int, y: Int, size : Int) = (size - 1) - y
override fun y(x: Int, y: Int, size : Int) = x
}, `180`{
override fun x(x: Int, y: Int, size : Int) = (size - 1) - x
override fun y(x: Int, y: Int, size : Int) = (size - 1) - y
}, `270`{
override fun x(x: Int, y: Int, size : Int) = y
override fun y(x: Int, y: Int, size : Int) = (size - 1) - x
};
abstract fun x(x: Int, y: Int, size : Int) : Int
abstract fun y(x: Int, y: Int, size : Int) : Int
}
class Solution {
fun solution(key: Array<IntArray>, lock: Array<IntArray>): Boolean {
enumValues<Direction>().forEach {
var rotated = rotate(key, it)
for(moveX in -(key.size - 1) .. (lock.size-1) + (key.size-1)) {
for(moveY in -(key.size - 1) .. (lock.size-1) + (key.size-1)) {
var movedKey = moveKey(rotated, lock.size, moveX, moveY)
var match = plus(movedKey, lock)
if(checkOpen(match)) return true
}
}
}
return false
}
fun checkOpen(matrix: Array<IntArray>) : Boolean {
return matrix.any{ a -> a.any{ it != 1 } }.not()
}
fun createMatrix(size : Int) : Array<IntArray> {
return Array(size, { IntArray(size, {0}) })
}
fun moveKey(key: Array<IntArray>, lockSize : Int, moveX : Int, moveY : Int) : Array<IntArray> {
var moveKey = createMatrix(lockSize)
for(x in 0 .. lockSize - 1){
for(y in 0 .. lockSize - 1){
var movedX = x + moveX
var movedY = y + moveY
var validation = x >= 0 && x < key.size && y >= 0 && y < key.size
var ableToMove = movedX >= 0 && movedX < lockSize && movedY >= 0 && movedY < lockSize
if(validation && ableToMove) {
moveKey[movedX][movedY] = key[x][y]
}
}
}
return moveKey
}
fun rotate(matrix: Array<IntArray>, direction: Direction) : Array<IntArray> {
return createMatrix(matrix.size).mapIndexed {i, e1 ->
e1.mapIndexed { j, _ ->
var newX = direction.x(i, j, matrix.size)
var newY = direction.y(i, j, matrix.size)
matrix[newX][newY]
}.toIntArray()
}.toTypedArray()
}
fun plus(matrixA: Array<IntArray>, matrixB: Array<IntArray>) : Array<IntArray> {
return matrixA.mapIndexed { i, e1 -> e1.mapIndexed { j, e2 -> e2 + matrixB[i][j] }.toIntArray() }.toTypedArray()
}
}
class SolutionTest(val solution : Solution, val testTool : TestStrategy = NormalTest()) {
/*
* 000 matrix[0][0] matrix[0][1] matrix[0][2]
* 100 matrix[1][0] matrix[1][1] matrix[1][2]
* 011 matrix[2][0] matrix[2][1] matrix[2][2]
*/
fun draw(matrix: Array<IntArray>) {
matrix.forEach{
it.forEach{
a ->print(a)
}
println("")
}
println("---")
}
fun testSolution() {
val key = arrayOf(intArrayOf(0,0,0),intArrayOf(1,0,0),intArrayOf(0,1,1))
val lock = arrayOf(intArrayOf(1,1,1),intArrayOf(1,1,0),intArrayOf(1,0,1))
val answer = true
testTool.test(answer) {
solution.solution(key, lock)
}
}
}
interface TestStrategy {
fun<T> test(answer : T, testBlock: () -> T)
}
class NormalTest : TestStrategy {
override fun<T> test(answer : T, testBlock: ()->T) {
val result = testBlock()
println("------------")
assertEquals(answer, result, "epected : $answer, actural : $result")
}
}
class EfficiencyTest : TestStrategy {
override fun<T> test(answer : T, testBlock: ()->T) {
val (result, duration) = measureTimedValue { testBlock() }
println("------------")
println("duration : $duration")
assertEquals(answer, result, "epected : $answer, actural : $result")
}
}
fun main() {
val solution = Solution()
val solutionTest = SolutionTest(solution)
solutionTest.testSolution()
}
ํ์ด๋ฐฉ์
์กฐ๊ธ ๋ฌด์ํ ๋ฐฉ๋ฒ์ผ์ง ๋ชจ๋ฅด์ง๋ง ์ด์ ์ ์๋ฌผ์ ์ ์ต๋ ํฌ๊ธฐ๊ฐ 20์ด๋ผ์ ๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ํ์ธํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ ๊ทผํ๋ค.
ํค์ ํ์ ๊ณผ ์์ง์์ ๋ฐ๋ฅธ ๋ณํ๋ ํค๊ฐ์ ๊ฐ์ง๊ณ ์ฌ ์ ์๋๋ก (roatate, moveKey) ํจ์๋ฅผ ๊ฐ๊ฐ ๊ตฌํํ๋ค.
moveKey๋ ์์ง์ธ ๊ฒฐ๊ณผ๋ก ์๋ฌผ์ ํฌ๊ธฐ์ 0๋ฐฐ์ด์์ ๋ณํ๋ ํค์ ๋๊ธฐ ๋ถ๋ถ๋ง 1์ด ๋๋๋ก ๋ฐฐ์ด์ ๋ฐํํ๊ณ ,
๋ต ๋์ถ์ ์๋ฌผ์ ์ ๋ณํ๋ ํค์ ๊ฐ ์์๊ฐ์ ๋ํด ๋ชจ๋ ์์๊ฐ 1์ด ๋์ค๋ ๊ฒฝ์ฐ๋ฅผ open์ผ๋ก ๊ท์ ํ๋ค.