「電脳少女プログラミング2088 | 壊レタ君を再構築」をKotlinでやってみた (途中) ので、公開したいと思います。
途中ですが、進んだら更新していきたいと思います。
また、解説は後で書くかもしれませんが、ランクD相当は書かないと思います。
郊外のスラム街(paizaランク:D相当)
fun main() {
val n = readLine()!!.toInt()
println(n / 2 + 100)
}
カジノ(paizaランク:D相当)
fun main() {
val dollar01 = readLine()!!.toInt()
val dollar05 = readLine()!!.toInt()
val dollar10 = readLine()!!.toInt()
println(dollar01 + 5 * dollar05 + 10 * dollar10)
}
ネオン街の裏路地(paizaランク:D相当)
private fun readInt(): Int = readLine()!!.toInt()
fun main() {
val n = readInt()
val max = (0 until n).map { readInt() }.maxBy { it }
println(max)
}
自然の残る公園(paizaランク:C相当)
private fun line(): String = readLine()!!
fun main() {
val (n,cx, cy) = line().split(' ').map { it.toInt() }
val nearNo = (1..n)
.map {
val (x, y) = line().split(" ").map { it.toInt() }
val l = (x-cx)*(x-cx) + (y-cy)*(y-cy)
it to l
}
.minBy { (_, l) -> l }
.first
println(nearNo)
}
ネオン街のクラブ(paizaランク:C相当)
kotlinはランキングに関係していないようですが、除外します。
廃マンションの一室(paizaランク:C相当)
import kotlin.math.abs
fun main() {
val n = readLine()!!.toInt()
var w = n
var i = 0
// 10進で10桁MAXとするなら3進で21桁ぐらい?(log 10^10 / log 3 ≒ = 21?)
val t = IntArray(size = 21)
do {
val d = w % 3
w /= 3
when (val v = d + t[i]) {
// 3は桁を上げる
3 -> {
t[i] = 0 // 元の桁は0
t[i + 1] = 1 // +1として桁を上げる
}
// 2は桁を上げて-1したこととする
2 -> {
t[i] = -1 // -1する
t[i + 1] = 1 // +1として桁を上げる
}
// そのまま
1, 0, -1 -> t[i] = v
// -2は桁を上げて+1したこととする
-2 -> {
t[i] = 1 // +1する
t[i + 1] = -1 // -1として桁を上げる
}
// -3は桁を上げる
-3 -> {
t[i] = 0 // 元の桁は0
t[i + 1] = -1 // -1として桁を上げる
}
// エラー
else -> error("n=$n, i=$i, w=$w, d=$d, t[i]=${t[i]}, v=$v")
}
i++
} while (abs(w) > 0 && i in t.indices)
// 表示を修正して特殊3進数の文字列作成
val text = t.reversed().dropWhile { it == 0 }.joinToString(separator = "") {
when (it) {
-1 -> "2"
0 -> "0"
1 -> "1"
else -> error("Illegal value=$it")
}
}.ifEmpty { "0" } // 少し手抜き
println(text)
}
この辺からローカルで試しながらでないと難しかった。
ギャングのアジト(paizaランク:B相当)
private fun line(): String = readLine()!!
fun main() {
val n = line().toInt()
for(i in 1..n) {
val l = line()
val r = l.reversed()
if(l != r) {
println("No")
return
}
}
println("Yes")
}
手抜きです…。
private fun line(): String = readLine()!!
fun main() {
val n = line().toInt()
for(i in 1..n) {
val l = line().split(" ").map { it.toInt() }
val nor = l.take(n / 2)
val rev = l.reversed().take(n / 2)
if(nor != rev) {
println("No")
return
}
}
println("Yes")
}
一応、あまり手抜きではないものです。
一番通りの繁華街(paizaランク:B相当)
private const val TERRITORY = '.'
private class Grid(private val width: Int, private val grid: List<Char>) {
init {
require(grid.size == width * width)
}
operator fun get(point: Point): Char? = get(point.x, point.y)
operator fun get(x: Int, y: Int): Char? =
if (x in 0 until width &&
y in 0 until width
) {
grid[y * width + x]
} else {
null
}
}
private data class Point(val x: Int, val y: Int)
private fun MutableSet<Set<Point>>.addIfTerritory(base: Point, diagonal: Point, g: Grid) {
val point2 = Point(diagonal.x, base.y)
val point3 = Point(base.x, diagonal.y)
if (g[base] == TERRITORY &&
g[point2] == TERRITORY &&
g[diagonal] == TERRITORY &&
g[point3] == TERRITORY
) {
add(setOf(base, point2, diagonal, point3))
}
}
private fun territoriesCount(width: Int, grid: List<Char>): Int {
val g = Grid(width, grid)
val territories = mutableSetOf<Set<Point>>()
for (x in 0 until width) {
for (y in 0 until width) {
val point = Point(x, y)
if (g[point] != TERRITORY) continue
for (dw in 1 until width) {
territories.addIfTerritory(point, Point(x + dw, y + dw), g)
territories.addIfTerritory(point, Point(x - dw, y - dw), g)
territories.addIfTerritory(point, Point(x - dw, y + dw), g)
territories.addIfTerritory(point, Point(x + dw, y - dw), g)
}
}
}
return territories.size
}
private fun line(): String = readLine()!!
fun main() {
val n = line().toInt()
val grid = (0 until n).map { line().toCharArray() }.flatMap { it.toList() }
println(territoriesCount(n, grid).toString())
}
この問題もローカルで試しながら行った。
テリトリーとなる正方形を4つの位置のSetとして扱って、更にSetを使って何種類になるのかをカウントしている。
新都心のハイウェイ(paizaランク:A相当)
private const val CAR_A: Int = 0
private const val CAR_B: Int = -1
private const val GOAL: Int = -2
private const val WALL: Int = Int.MIN_VALUE
private val EMPTY: Int? = null
private class Cells(val h: Int, val w: Int, val cells: MutableList<Int?>) {
operator fun get(x: Int, y: Int): Int? =
if (x in 0 until w && y in 0 until h) {
cells[y * w + x]
} else {
WALL // 範囲外は壁として扱う
}
operator fun set(x: Int, y: Int, value: Int?) {
cells[y * w + x] = value
}
}
private tailrec fun setupGoalInner(cells: Cells, x: Int, y: Int, dx: Int, dy: Int) {
if (cells[x + dx, y + dy] != WALL) {
cells[x + dx, y + dy] = GOAL
setupGoalInner(cells, x = x + dx, y = y + dy, dx = dx, dy = dy)
}
}
private fun setupGoal(cells: Cells) {
// Bの位置を探す
val indexB = cells.cells.indexOfFirst { it == CAR_B }
val carBx = indexB % cells.w
val carBy = indexB / cells.w
// Bの位置から十字にゴール判定で埋める
setupGoalInner(cells, carBx, carBy, dx = 1, dy = 0)
setupGoalInner(cells, carBx, carBy, dx = -1, dy = 0)
setupGoalInner(cells, carBx, carBy, dx = 0, dy = 1)
setupGoalInner(cells, carBx, carBy, dx = 0, dy = -1)
}
private tailrec fun foundCarB(cells: Cells, step: Int): Int {
var assigned = false
for (y in 0 until cells.h) {
for (x in 0 until cells.w) {
if (cells[x, y] != step) continue
assigned = true
// ゴールに到達していたら終了
if (cells[x + 1, y] == GOAL) return step + 1
if (cells[x - 1, y] == GOAL) return step + 1
if (cells[x, y + 1] == GOAL) return step + 1
if (cells[x, y - 1] == GOAL) return step + 1
// 次の移動ステップを代入
if (cells[x + 1, y] == EMPTY) cells[x + 1, y] = step + 1
if (cells[x - 1, y] == EMPTY) cells[x - 1, y] = step + 1
if (cells[x, y + 1] == EMPTY) cells[x, y + 1] = step + 1
if (cells[x, y - 1] == EMPTY) cells[x, y - 1] = step + 1
}
}
// 代入がなかったら見つからないとして終了
if (assigned.not()) return -1
// 次
return foundCarB(cells, step = step + 1)
}
private fun foundCarB(cells: Cells): Int {
// Aの位置を取得
val indexA = cells.cells.indexOfFirst { it == CAR_A }
val carAx = indexA % cells.w
val carAy = indexA / cells.w
// ゴールを設定
setupGoal(cells)
// Aの位置のゴールチェック
if (cells[carAx, carAy] == GOAL) return 0
// 探す
return foundCarB(cells, step = 0)
}
private fun line(): String = readLine()!!
fun main() {
val (h, w) = line().split(" ").map { it.toInt() }
val cells = (0 until h).map { line().toCharArray() }.flatMap { it.toList() }.map {
when (it) {
'A' -> CAR_A
'B' -> CAR_B
'#' -> WALL
'.' -> EMPTY
else -> error("Invalid cell: $it")
}
}.let { Cells(h, w, it.toMutableList()) }
println(foundCarB(cells))
}
最初は、経路が見つからなかったときの処理を作成しなかったため、無限ループにしてしまっていました。
Aが移動する移動数を代入していく形をベースに求めようとしています。
指摘内容としては、効率が良くないようです。
そのうち、他の方の投稿なども見てみたいと思います。
思い出の屋上(paizaランク:S相当)
import kotlin.math.abs
import kotlin.math.max
private val EMPTY: Int? = null
private class Area(val h: Int, val w: Int) {
val cells: MutableList<Int?> = MutableList(size = h * w) { EMPTY }
operator fun get(row: Int, col: Int): Int? =
if (row in 1..h && col in 1..w) {
cells[(row - 1) * w + (col - 1)]
} else {
EMPTY // 範囲外は空として扱う
}
operator fun set(row: Int, col: Int, value: Int?) {
check(this[row, col] == EMPTY) { "Already set. row=$row, col=$col, ${this[row, col]}" }
if (row in 1..h && col in 1..w) {
cells[(row - 1) * w + (col - 1)] = value
}
}
override fun toString(): String {
return buildString {
for (row in 1..h) {
for (col in 1..w) {
append(
when (val c = this@Area[row, col]) {
EMPTY -> '.'
else -> c!!.toString(radix = 16).last()
}
)
}
appendLine()
}
}
}
}
private fun setupTerritory(area: Area, row: Int, col: Int, distance: Int) {
for (dCol in -distance..distance) {
val rowDistance = distance - abs(dCol)
for (dRow in 0..rowDistance) {
if (dRow == 0) {
area[row, col + dCol] = distance
} else {
area[row + dRow, col + dCol] = distance
area[row - dRow, col + dCol] = distance
}
}
}
}
private fun canEstablishTerritory(area: Area, row: Int, col: Int): Int? {
if (area[row, col] != EMPTY) return null
val maxDistance = max(area.h, area.w)
for (distance in 0..maxDistance) {
for (dCol in -distance..distance) {
val rowDistance = distance - abs(dCol)
if (rowDistance == 0) {
if (area[row, col + dCol] != EMPTY) return distance - 1
} else {
if (area[row + rowDistance, col + dCol] != EMPTY) return distance - 1
if (area[row - rowDistance, col + dCol] != EMPTY) return distance - 1
}
}
}
return maxDistance
}
private fun findMaxTerritorySize(area: Area): Int =
(1..area.h).flatMap { row -> (1..area.w).map { col -> Pair(row, col) } }
.mapNotNull { (row, col) -> canEstablishTerritory(area, row = row, col = col) }
.maxOrNull() ?: -1
private fun line(): String = readLine()!!
fun main() {
val (h, w, m) = line().split(" ").map { it.toInt() }
val area = Area(h, w)
(1..m).map { line() }
.map { line -> line.split(" ").map { it.toInt() } }
.forEach { (row, col, distance) ->
setupTerritory(area, row = row, col = col, distance = distance)
}
println(findMaxTerritorySize(area))
}
この問題もローカルで試しながら行った。
コツコツやってきましたが、プログラムの問題は全部記載したので、本投稿は終了です。
気が向けば解説の追記などを書くかもしれません。