Problem
Given a 6×6 2D Array, arr:
1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
We define an hourglass in A to be a subset of values with indices
falling in this pattern in arr‘s graphical representation:a b c d e f g
There are 16 hourglasses in arr, and an hourglass sum is the
sum of an hourglass’ values. Calculate the hourglass sum for every
hourglass in arr, then print the maximum hourglass sum.For example, given the 2D array:
-9 -9 -9 1 1 1 0 -9 0 4 3 2 -9 -9 -9 1 2 3 0 0 8 6 6 0 0 0 0 -2 0 0 0 0 1 2 4 0
We calculate the following 16 hourglass values:
-63, -34, -9, 12, -10, 0, 28, 23, -27, -11, -2, 10, 9, 17, 25, 18
Our highest hourglass value is 28 from the hourglass:
0 4 3 1 8 6 6
Note: If you have already solved the Java domain’s Java 2D Array
challenge, you may wish to skip this challenge.Function Description
Complete the function hourglassSum in the editor below. It should
return an integer, the maximum hourglass sum in the array.hourglassSum has the following parameter(s):
- arr: an array of integers
Sample Input
1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 2 4 4 0 0 0 0 2 0 0 0 0 1 2 4 0
Sample Output
19
Explanation
arr contains the following hourglasses:
The hourglass with the maximum sum (19) is:
2 4 4 2 1 2 4
Following is my imperative style Solution:
def hourglassSum(arr: Array[Array[Int]]): Int = {
def sum(rowNumber: Int, columnNumber: Int): Int = {
var oneHourglassSum = 0
for {
i <- 0 to 2
j <- 0 to 2
} yield {
val cumulativeSum = if (i == 1 && (j == 0 || j == 2)) 0
else arr(i + rowNumber)(j + columnNumber)
oneHourglassSum += cumulativeSum
}
oneHourglassSum
}
def max(x: Int, y: Int): Int = if (x > y) x else y
var hourglassMaxSum = 0
for {
rowOffset <- 0 to 3
columnOffset <- 0 to 3
} yield {
hourglassMaxSum = max(sum(rowOffset, columnOffset), hourglassMaxSum)
}
hourglassMaxSum
}
Solution
There’s no need to write a max()
method. The Standard Library provides for that.
A for
comprehension, with a yield
clause, produces a result. So instead of using a mutable var
to capture and collect the results of the yield
you should capture them directly.
val res = for {...} yield {...}
Or, if you want to process the results more directly, i.e. without the intermediate variable, you can use the somewhat awkward parentheses construct.
def hourglassSum(arr: Array[Array[Int]]): Int = {
(for {
x <- 0 to 3
y <- 0 to 3
} yield {
arr(y)(x) + arr(y)(x+1) + arr(y)(x+2) +
arr(y+1)(x+1) +
arr(y+2)(x) + arr(y+2)(x+1) + arr(y+2)(x+2)
}).max
}