From 0616fdc719f762b5a47e29f7904d1f49858c900f Mon Sep 17 00:00:00 2001 From: Taehong Kim Date: Sat, 12 Mar 2022 16:03:29 +0900 Subject: [PATCH] =?UTF-8?q?feature=20:=20=EB=9E=9C=EB=8D=A4=20=EC=8A=A4?= =?UTF-8?q?=EB=8F=84=EC=BF=A0=20=EB=A7=B5=20api=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bin/main/io/sudoku/sudoku/math/Matrix.kt | 22 +++++++ .../sudoku/controller/SudokuController.kt | 21 +++++++ .../io/sudoku/sudoku/sudoku/model/Sudoku.kt | 21 +++++++ .../sudoku/sudoku/model/SudokuRequest.kt | 10 +++ .../sudoku/sudoku/service/SudokuService.kt | 8 +++ .../sudoku/service/SudokuServiceImpl.kt | 63 +++++++++++++++++++ sudoku-back/build.gradle.kts | 2 + .../kotlin/io/sudoku/sudoku/math/Matrix.kt | 22 +++++++ .../sudoku/controller/SudokuController.kt | 21 +++++++ .../io/sudoku/sudoku/sudoku/model/Sudoku.kt | 21 +++++++ .../sudoku/sudoku/model/SudokuRequest.kt | 10 +++ .../sudoku/sudoku/service/SudokuService.kt | 8 +++ .../sudoku/service/SudokuServiceImpl.kt | 63 +++++++++++++++++++ 13 files changed, 292 insertions(+) create mode 100644 sudoku-back/bin/main/io/sudoku/sudoku/math/Matrix.kt create mode 100644 sudoku-back/bin/main/io/sudoku/sudoku/sudoku/controller/SudokuController.kt create mode 100644 sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/Sudoku.kt create mode 100644 sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt create mode 100644 sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuService.kt create mode 100644 sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt create mode 100644 sudoku-back/src/main/kotlin/io/sudoku/sudoku/math/Matrix.kt create mode 100644 sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/controller/SudokuController.kt create mode 100644 sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/Sudoku.kt create mode 100644 sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt create mode 100644 sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuService.kt create mode 100644 sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt diff --git a/sudoku-back/bin/main/io/sudoku/sudoku/math/Matrix.kt b/sudoku-back/bin/main/io/sudoku/sudoku/math/Matrix.kt new file mode 100644 index 0000000..eec3e92 --- /dev/null +++ b/sudoku-back/bin/main/io/sudoku/sudoku/math/Matrix.kt @@ -0,0 +1,22 @@ +package io.sudoku.sudoku.math + +operator fun List.times(other: List): List { + assert(this.size == 9) + assert(this.size == other.size) + + return Array(9) { it }.let { + it[0] = this[0] * other[0] + this[1] * other[3] + this[2] * other[6] + it[1] = this[0] * other[1] + this[1] * other[4] + this[2] * other[7] + it[2] = this[0] * other[2] + this[1] * other[5] + this[2] * other[8] + + it[3] = this[3] * other[0] + this[4] * other[3] + this[5] * other[6] + it[4] = this[3] * other[1] + this[4] * other[4] + this[5] * other[7] + it[5] = this[3] * other[2] + this[4] * other[5] + this[5] * other[8] + + it[6] = this[6] * other[0] + this[7] * other[3] + this[8] * other[6] + it[7] = this[6] * other[1] + this[7] * other[4] + this[8] * other[7] + it[8] = this[6] * other[2] + this[7] * other[5] + this[8] * other[8] + + it.toList() + } +} \ No newline at end of file diff --git a/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/controller/SudokuController.kt b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/controller/SudokuController.kt new file mode 100644 index 0000000..3be24d5 --- /dev/null +++ b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/controller/SudokuController.kt @@ -0,0 +1,21 @@ +package io.sudoku.sudoku.sudoku.controller + +import io.sudoku.sudoku.sudoku.model.Sudoku +import io.sudoku.sudoku.sudoku.model.SudokuRequest +import io.sudoku.sudoku.sudoku.service.SudokuService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/sudoku") +class SudokuController { + + @Autowired + private lateinit var sudokuService: SudokuService; + + @GetMapping("/random") + fun getRandomMap(sudokuRequest: SudokuRequest): Sudoku + = sudokuService.getRandomMap(sudokuRequest) +} \ No newline at end of file diff --git a/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/Sudoku.kt b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/Sudoku.kt new file mode 100644 index 0000000..ee8f3e5 --- /dev/null +++ b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/Sudoku.kt @@ -0,0 +1,21 @@ +package io.sudoku.sudoku.sudoku.model + +typealias Board = List> + +data class Sudoku(val map: Board) + +/** + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * */ \ No newline at end of file diff --git a/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt new file mode 100644 index 0000000..6602a98 --- /dev/null +++ b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt @@ -0,0 +1,10 @@ +package io.sudoku.sudoku.sudoku.model + +import org.hibernate.validator.constraints.Range + +data class SudokuRequest( + + val seed: Long? = null, + + @Range(min = 18, max = 81) val showCount: Int, +) diff --git a/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuService.kt b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuService.kt new file mode 100644 index 0000000..75320c7 --- /dev/null +++ b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuService.kt @@ -0,0 +1,8 @@ +package io.sudoku.sudoku.sudoku.service + +import io.sudoku.sudoku.sudoku.model.Sudoku +import io.sudoku.sudoku.sudoku.model.SudokuRequest + +interface SudokuService { + fun getRandomMap(sudokuRequest: SudokuRequest): Sudoku +} \ No newline at end of file diff --git a/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt new file mode 100644 index 0000000..fd81c01 --- /dev/null +++ b/sudoku-back/bin/main/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt @@ -0,0 +1,63 @@ +package io.sudoku.sudoku.sudoku.service + +import io.sudoku.sudoku.math.times +import io.sudoku.sudoku.sudoku.model.Sudoku +import io.sudoku.sudoku.sudoku.model.SudokuRequest +import org.springframework.stereotype.Service +import java.util.* + +@Service +class SudokuServiceImpl : SudokuService { + + override fun getRandomMap(sudokuRequest: SudokuRequest): Sudoku { + val s0 = sudokuRequest.seed?.let { + getLine(it) + } ?: getLine() + + val map = getMap(s0) + val ret = filterMap(map, sudokuRequest.showCount) + + return Sudoku(ret) + } + + private fun getLine(): List = (1..9).toList().shuffled() + + private fun getLine(seed: Long): List = (1..9).toList().shuffled(Random(seed)) + + private fun getMap(s0: List): List> { + + val x1 = listOf(0, 0, 1, 1, 0, 0, 0, 1, 0) + val x2 = listOf(0, 1, 0, 0, 0, 1, 1, 0, 0) + + val s1 = x2 * s0 + val s2 = x1 * s0 + val s3 = s0 * x1 + val s4 = x2 * s0 * x1 + val s5 = x1 * s0 * x1 + val s6 = s0 * x2 + val s7 = x2 * s0 * x2 + val s8 = x1 * s0 * x2 + + return listOf(s0, s1, s2, s3, s4, s5, s6, s7, s8) + } + + private fun filterMap(map: List>, showCount: Int): List> { + var random = Random() + + var cnt = 0 + var ret = Array(9) { Array(9) { 0 } } + + while (true) { + var i = random.nextInt(8) + 1 + var j = random.nextInt(8) + 1 + + if (ret[i][j] == 0 && random.nextBoolean()) { + ret[i][j] = map[i][j] + cnt++ + if (cnt >= showCount) { + return ret.map { it.toList() }.toList() + } + } + } + } +} \ No newline at end of file diff --git a/sudoku-back/build.gradle.kts b/sudoku-back/build.gradle.kts index 0320955..dd22595 100644 --- a/sudoku-back/build.gradle.kts +++ b/sudoku-back/build.gradle.kts @@ -28,6 +28,8 @@ dependencies { // spring boot dependency 설정 implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") + // been validation + implementation("org.springframework.boot:spring-boot-starter-validation:2.6.4") // kotlin dependency 설정 implementation("org.jetbrains.kotlin:kotlin-reflect") diff --git a/sudoku-back/src/main/kotlin/io/sudoku/sudoku/math/Matrix.kt b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/math/Matrix.kt new file mode 100644 index 0000000..eec3e92 --- /dev/null +++ b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/math/Matrix.kt @@ -0,0 +1,22 @@ +package io.sudoku.sudoku.math + +operator fun List.times(other: List): List { + assert(this.size == 9) + assert(this.size == other.size) + + return Array(9) { it }.let { + it[0] = this[0] * other[0] + this[1] * other[3] + this[2] * other[6] + it[1] = this[0] * other[1] + this[1] * other[4] + this[2] * other[7] + it[2] = this[0] * other[2] + this[1] * other[5] + this[2] * other[8] + + it[3] = this[3] * other[0] + this[4] * other[3] + this[5] * other[6] + it[4] = this[3] * other[1] + this[4] * other[4] + this[5] * other[7] + it[5] = this[3] * other[2] + this[4] * other[5] + this[5] * other[8] + + it[6] = this[6] * other[0] + this[7] * other[3] + this[8] * other[6] + it[7] = this[6] * other[1] + this[7] * other[4] + this[8] * other[7] + it[8] = this[6] * other[2] + this[7] * other[5] + this[8] * other[8] + + it.toList() + } +} \ No newline at end of file diff --git a/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/controller/SudokuController.kt b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/controller/SudokuController.kt new file mode 100644 index 0000000..3be24d5 --- /dev/null +++ b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/controller/SudokuController.kt @@ -0,0 +1,21 @@ +package io.sudoku.sudoku.sudoku.controller + +import io.sudoku.sudoku.sudoku.model.Sudoku +import io.sudoku.sudoku.sudoku.model.SudokuRequest +import io.sudoku.sudoku.sudoku.service.SudokuService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/sudoku") +class SudokuController { + + @Autowired + private lateinit var sudokuService: SudokuService; + + @GetMapping("/random") + fun getRandomMap(sudokuRequest: SudokuRequest): Sudoku + = sudokuService.getRandomMap(sudokuRequest) +} \ No newline at end of file diff --git a/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/Sudoku.kt b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/Sudoku.kt new file mode 100644 index 0000000..ee8f3e5 --- /dev/null +++ b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/Sudoku.kt @@ -0,0 +1,21 @@ +package io.sudoku.sudoku.sudoku.model + +typealias Board = List> + +data class Sudoku(val map: Board) + +/** + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * | 1 2 3 | 1 2 3 | 1 2 3 | + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + * */ \ No newline at end of file diff --git a/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt new file mode 100644 index 0000000..6602a98 --- /dev/null +++ b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/model/SudokuRequest.kt @@ -0,0 +1,10 @@ +package io.sudoku.sudoku.sudoku.model + +import org.hibernate.validator.constraints.Range + +data class SudokuRequest( + + val seed: Long? = null, + + @Range(min = 18, max = 81) val showCount: Int, +) diff --git a/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuService.kt b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuService.kt new file mode 100644 index 0000000..75320c7 --- /dev/null +++ b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuService.kt @@ -0,0 +1,8 @@ +package io.sudoku.sudoku.sudoku.service + +import io.sudoku.sudoku.sudoku.model.Sudoku +import io.sudoku.sudoku.sudoku.model.SudokuRequest + +interface SudokuService { + fun getRandomMap(sudokuRequest: SudokuRequest): Sudoku +} \ No newline at end of file diff --git a/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt new file mode 100644 index 0000000..fd81c01 --- /dev/null +++ b/sudoku-back/src/main/kotlin/io/sudoku/sudoku/sudoku/service/SudokuServiceImpl.kt @@ -0,0 +1,63 @@ +package io.sudoku.sudoku.sudoku.service + +import io.sudoku.sudoku.math.times +import io.sudoku.sudoku.sudoku.model.Sudoku +import io.sudoku.sudoku.sudoku.model.SudokuRequest +import org.springframework.stereotype.Service +import java.util.* + +@Service +class SudokuServiceImpl : SudokuService { + + override fun getRandomMap(sudokuRequest: SudokuRequest): Sudoku { + val s0 = sudokuRequest.seed?.let { + getLine(it) + } ?: getLine() + + val map = getMap(s0) + val ret = filterMap(map, sudokuRequest.showCount) + + return Sudoku(ret) + } + + private fun getLine(): List = (1..9).toList().shuffled() + + private fun getLine(seed: Long): List = (1..9).toList().shuffled(Random(seed)) + + private fun getMap(s0: List): List> { + + val x1 = listOf(0, 0, 1, 1, 0, 0, 0, 1, 0) + val x2 = listOf(0, 1, 0, 0, 0, 1, 1, 0, 0) + + val s1 = x2 * s0 + val s2 = x1 * s0 + val s3 = s0 * x1 + val s4 = x2 * s0 * x1 + val s5 = x1 * s0 * x1 + val s6 = s0 * x2 + val s7 = x2 * s0 * x2 + val s8 = x1 * s0 * x2 + + return listOf(s0, s1, s2, s3, s4, s5, s6, s7, s8) + } + + private fun filterMap(map: List>, showCount: Int): List> { + var random = Random() + + var cnt = 0 + var ret = Array(9) { Array(9) { 0 } } + + while (true) { + var i = random.nextInt(8) + 1 + var j = random.nextInt(8) + 1 + + if (ret[i][j] == 0 && random.nextBoolean()) { + ret[i][j] = map[i][j] + cnt++ + if (cnt >= showCount) { + return ret.map { it.toList() }.toList() + } + } + } + } +} \ No newline at end of file