You are given a matrix, consisting of three rows and three columns, represented as an array A of nine integers. The rows of the matrix are numbered from 0 to 2 (from top to bottom) and the columns are numbered from 0 to 2 (from left to right). The matrix element in the J-th row and K-th column corresponds to the array element A[J*3 + K]. For example, the matrix below corresponds to array [0, 2, 3, 4, 1, 1, 1, 3, 1].
In one move you can increment any element by 1.
Your task is to find a matrix whose elements in each row and each column sum to an equal value, which can be constructed from the given matrix in a minimal number of moves.
Write a function:
fun solution(A: IntArray): IntArray
that, given an array A of nine integers, returns an array of nine integers, representing the matrix described above. If there are several possible answers, the function may return any of them.
Examples:
1. Given A = [0, 2, 3, 4, 1, 1, 1, 3, 1], the function could return [1, 2, 3, 4, 1, 1, 1, 3, 2]. The sum of elements in each row and each column of the returned matrix is 6. Two increments by 1 are enough. You can increment A[0] and A[8] (top-left and bottom-right matrix elements). This gives [1, 2, 3, 4, 1, 1, 1, 3, 2], which satisfies the statement's conditions. Alternatively, you can increment A[2] and A[6] (top-right and bottom-left matrix elements). This gives another correct solution: [0, 2, 4, 4, 1, 1, 2, 3, 1].
2. Given A = [1, 1, 1, 2, 2, 1, 2, 2, 1], the function should return [1, 1, 3, 2, 2, 1, 2, 2, 1]. The sum of elements in each row and each column of the returned matrix is 5. Two increments by 1 are enough. You can increment A[2] (top-right matrix element) twice. In this case, there are no other correct solutions.
Write an efficient algorithm for the following assumptions:
- array A contains nine elements;
- each element of array A is an integer within the range [0..100,000,000].
// you can also use imports, for example:
// import kotlin.math.*
// you can write to stdout for debugging purposes, e.g.
// println("this is a debug message")
val matrixSize = 3
val listRows = { list: IntArray -> list.asList().chunked(matrixSize) }
val listCols = { list: IntArray ->
sequence {
for (i in 0 until matrixSize) {
for (j in 0 until matrixSize) {
yield(list[j * matrixSize + i])
}
}
}.chunked(matrixSize).toList()
}
fun solution(input: IntArray): IntArray {
val rowSums = listRows(input).map { it.sum() }.toIntArray()
val colSums = listCols(input).map { it.sum() }.toIntArray()
val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).maxOrNull()!!
val targetTotal = maxSum * matrixSize
var currentTotal = input.sum()
// while not very functional, I can at least make the function pure ¯\_(ツ)_/¯
val modifiedMatrix = input.clone()
while (currentTotal < targetTotal) {
for (i in 0 until matrixSize) {
if (rowSums[i] == maxSum) {
continue
}
for (j in 0 until matrixSize) {
if (colSums[j] == maxSum) {
continue
}
val increment = min(maxSum - rowSums[i], maxSum - colSums[j])
// mutations coming right up:
modifiedMatrix[(i * matrixSize) + j] += increment
rowSums[i] += increment
colSums[j] += increment
currentTotal += increment
break
}
}
}
return modifiedMatrix
}
solution2(testData2).asList()
// you can also use imports, for example:
// import kotlin.math.*
import java.lang.Integer.min
// you can write to stdout for debugging purposes, e.g.
// println("this is a debug message")
val matrixSize = 3
val listRows = { list: IntArray -> list.asList().chunked(matrixSize) }
val listCols = { list: IntArray ->
sequence {
for (i in 0 until matrixSize) {
for (j in 0 until matrixSize) {
yield(list[j * matrixSize + i])
}
}
}.chunked(matrixSize).toList()
}
fun solution(input: IntArray): IntArray {
val rowSums = listRows(input).map { it.sum() }.toIntArray()
val colSums = listCols(input).map { it.sum() }.toIntArray()
val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).maxOrNull()!!
val targetTotal = maxSum * matrixSize
var currentTotal = input.sum()
// while not very functional, I can at least make the function pure ¯\_(ツ)_/¯
val modifiedMatrix = input.clone()
while (currentTotal < targetTotal) {
for (i in 0 until matrixSize) {
if (rowSums[i] == maxSum) {
continue
}
for (j in 0 until matrixSize) {
if (colSums[j] == maxSum) {
continue
}
val increment = min(maxSum - rowSums[i], maxSum - colSums[j])
// mutations coming right up:
modifiedMatrix[(i * matrixSize) + j] += increment
rowSums[i] += increment
colSums[j] += increment
currentTotal += increment
break
}
}
}
return modifiedMatrix
}
solution.kt:23:63: error: unresolved reference: maxOrNull val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).maxOrNull()!! ^
// you can also use imports, for example:
// import kotlin.math.*
import java.lang.Integer.min
// you can write to stdout for debugging purposes, e.g.
// println("this is a debug message")
val matrixSize = 3
val listRows = { list: IntArray -> list.asList().chunked(matrixSize) }
val listCols = { list: IntArray ->
sequence {
for (i in 0 until matrixSize) {
for (j in 0 until matrixSize) {
yield(list[j * matrixSize + i])
}
}
}.chunked(matrixSize).toList()
}
fun solution(input: IntArray): IntArray {
val rowSums = listRows(input).map { it.sum() }.toIntArray()
val colSums = listCols(input).map { it.sum() }.toIntArray()
val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).max()!!
val targetTotal = maxSum * matrixSize
var currentTotal = input.sum()
// while not very functional, I can at least make the function pure ¯\_(ツ)_/¯
val modifiedMatrix = input.clone()
while (currentTotal < targetTotal) {
for (i in 0 until matrixSize) {
if (rowSums[i] == maxSum) {
continue
}
for (j in 0 until matrixSize) {
if (colSums[j] == maxSum) {
continue
}
val increment = min(maxSum - rowSums[i], maxSum - colSums[j])
// mutations coming right up:
modifiedMatrix[(i * matrixSize) + j] += increment
rowSums[i] += increment
colSums[j] += increment
currentTotal += increment
break
}
}
}
return modifiedMatrix
}
// you can also use imports, for example:
// import kotlin.math.*
import java.lang.Integer.min
// you can write to stdout for debugging purposes, e.g.
// println("this is a debug message")
val matrixSize = 3
val listRows = { list: IntArray -> list.asList().chunked(matrixSize) }
val listCols = { list: IntArray ->
sequence {
for (i in 0 until matrixSize) {
for (j in 0 until matrixSize) {
yield(list[j * matrixSize + i])
}
}
}.chunked(matrixSize).toList()
}
fun solution(input: IntArray): IntArray {
val rowSums = listRows(input).map { it.sum() }.toIntArray()
val colSums = listCols(input).map { it.sum() }.toIntArray()
val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).max()!!
val targetTotal = maxSum * matrixSize
var currentTotal = input.sum()
// while not very functional, I can at least make the function pure ¯\_(ツ)_/¯
val modifiedMatrix = input.clone()
while (currentTotal < targetTotal) {
for (i in 0 until matrixSize) {
if (rowSums[i] == maxSum) {
continue
}
for (j in 0 until matrixSize) {
if (colSums[j] == maxSum) {
continue
}
// the maximum safe increment is the minimum difference between target/actual row/col sum
val increment = min(maxSum - rowSums[i], maxSum - colSums[j])
// mutations coming right up:
modifiedMatrix[(i * matrixSize) + j] += increment
rowSums[i] += increment
colSums[j] += increment
currentTotal += increment
break
}
}
}
return modifiedMatrix
}
// you can also use imports, for example:
// import kotlin.math.*
import java.lang.Integer.min
// you can write to stdout for debugging purposes, e.g.
// println("this is a debug message")
val matrixSize = 3
val listRows = { list: IntArray -> list.asList().chunked(matrixSize) }
val listCols = { list: IntArray ->
sequence {
for (i in 0 until matrixSize) {
for (j in 0 until matrixSize) {
yield(list[j * matrixSize + i])
}
}
}.chunked(matrixSize).toList()
}
fun solution(input: IntArray): IntArray {
val rowSums = listRows(input).map { it.sum() }.toIntArray()
val colSums = listCols(input).map { it.sum() }.toIntArray()
val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).max()!!
val targetTotal = maxSum * matrixSize
var currentTotal = input.sum()
// while not very functional, I can at least make the function pure ¯\_(ツ)_/¯
val modifiedMatrix = input.clone()
while (currentTotal < targetTotal) {
for (i in 0 until matrixSize) {
if (rowSums[i] == maxSum) {
continue
}
for (j in 0 until matrixSize) {
if (colSums[j] == maxSum) {
continue
}
// the maximum safe increment is the minimum difference between target/actual row/col sum
val increment = min(maxSum - rowSums[i], maxSum - colSums[j])
// mutations coming right up:
modifiedMatrix[(i * matrixSize) + j] += increment
rowSums[i] += increment
colSums[j] += increment
currentTotal += increment
break
}
}
}
return modifiedMatrix
}
// you can also use imports, for example:
// import kotlin.math.*
import java.lang.Integer.min
// you can write to stdout for debugging purposes, e.g.
// println("this is a debug message")
val matrixSize = 3
val listRows = { list: IntArray -> list.asList().chunked(matrixSize) }
val listCols = { list: IntArray ->
sequence {
for (i in 0 until matrixSize) {
for (j in 0 until matrixSize) {
yield(list[j * matrixSize + i])
}
}
}.chunked(matrixSize).toList()
}
fun solution(input: IntArray): IntArray {
val rowSums = listRows(input).map { it.sum() }.toIntArray()
val colSums = listCols(input).map { it.sum() }.toIntArray()
val maxSum = intArrayOf(rowSums.max()!!, colSums.max()!!).max()!!
val targetTotal = maxSum * matrixSize
var currentTotal = input.sum()
// while not very functional, I can at least make the function pure ¯\_(ツ)_/¯
val modifiedMatrix = input.clone()
while (currentTotal < targetTotal) {
for (i in 0 until matrixSize) {
if (rowSums[i] == maxSum) {
continue
}
for (j in 0 until matrixSize) {
if (colSums[j] == maxSum) {
continue
}
// the maximum safe increment is the minimum difference between target/actual row/col sum
val increment = min(maxSum - rowSums[i], maxSum - colSums[j])
// mutations coming right up:
modifiedMatrix[(i * matrixSize) + j] += increment
rowSums[i] += increment
colSums[j] += increment
currentTotal += increment
break
}
}
}
return modifiedMatrix
}
The solution obtained perfect score.
Random matrices with medium value range, max - min <= 2000, and two zeros.