class Solution { fun movesToChessboard(board: Array): Int { val n = board.size fun row(r: Int): List = board[r].asList() fun col(c: Int): List = (0 until n).map { r -> board[r][c] }.toList() run { // validate rows val rToCnt = (0 until n).map { r -> row(r) }.groupingBy { it }.eachCount() if (rToCnt.size != 2) return -1 if (rToCnt.keys.none { it.first() == 0 }) return -1 if (rToCnt.keys.none { it.first() == 1 }) return -1 val r0 = rToCnt.keys.first { it.first() == 0 } val r1 = rToCnt.keys.first { it.first() == 1 } val deltaR = rToCnt.getValue(r0) - rToCnt.getValue(r1) if (deltaR !in -1..1) return -1 // validate cols val cToCnt = (0 until n).map { c -> col(c) }.groupingBy { it }.eachCount() if (cToCnt.size != 2) return -1 if (cToCnt.keys.none { it.first() == 0 }) return -1 if (cToCnt.keys.none { it.first() == 1 }) return -1 val c0 = cToCnt.keys.first { it.first() == 0 } val c1 = cToCnt.keys.first { it.first() == 1 } val deltaC = cToCnt.getValue(c0) - cToCnt.getValue(c1) if (deltaC !in -1..1) return -1 // validate row/col sums val rSumToCnt = rToCnt.map { (r, cnt) -> r.sum() to cnt }.toMap() val cSumToCnt = cToCnt.map { (c, cnt) -> c.sum() to cnt }.toMap() if (n % 2 == 0 && rSumToCnt.keys.any { it != n / 2 }) return -1 if (n % 2 == 0 && cSumToCnt.keys.any { it != n / 2 }) return -1 if (n % 2 == 1) { val majSum = rSumToCnt.maxBy { (k, v) -> v }.let { (k, v) -> k } val minSum = rSumToCnt.toList().single { (k, v) -> k != majSum }.let { (k, v) -> k } if (majSum != (n / 2) && majSum != (n + 1) / 2) return -1 if (minSum != n - majSum) return -1 if (cSumToCnt.getValue(majSum) != rSumToCnt.getValue(majSum)) return -1 if (cSumToCnt.getValue(minSum) != rSumToCnt.getValue(minSum)) return -1 } } val rowDataRaw = IntArray(n) { r -> board[r][0] } val cnt0 = swapCnt(rowDataRaw, 0) val cnt1 = swapCnt(rowDataRaw, 1) val colDataRow0 = board.first { it[0] == 0 } val colDataRow1 = board.first { it[0] == 1 } val r0c0 = cnt0 + swapCnt(colDataRow0, 0) val r0c1 = cnt0 + swapCnt(colDataRow0, 1) val r1c0 = cnt1 + swapCnt(colDataRow1, 0) val r1c1 = cnt1 + swapCnt(colDataRow1, 1) return listOf(r0c0, r0c1, r1c0, r1c1).filterNotNull().minOrNull() ?: -1 } private fun swapCnt(arr: IntArray, v0: Int): Int? { check(v0 in 0..1) var i = 0 var exp = v0 var cnt0 = 0 var cnt1 = 0 while (i < arr.size) { if (arr[i] != exp && arr[i] == 0) cnt0++ if (arr[i] != exp && arr[i] == 1) cnt1++ i++ exp = exp xor 1 } return if (cnt0 == cnt1) cnt0 else null } } private operator fun Int?.plus(other: Int?) = when { this == null -> null other == null -> null else -> this!! + other!! }