While working through this HackerRank challenge to prepare for interviews, stumbled across a blocker.
Basically want to create a function hourglassSum that should return an integer (the maximum hourglass sum in the array). Given a 6 x 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
There are 16 hourglasses in arr, and an hourglass sum is the sum of an hourglass' values. In that case, the sum of an hourglass' is 7.
This is the code I currently have (it's commented so it should be easy to understand the decisions being made too)
def hourglassSum(arr):
#print(f"arr: {arr}")
#print(f"arr[1]: {arr[1]}")
#print(f"arr[1][1]: {arr[1][1]}")
num_rows = len(arr)
num_cols = len(arr[0])
hg_total = 0
hg_current_sum = 0
hg_max_sum = 0
i = 0
j = 0
# There's no hourglass
if 0 <= num_rows <= 3 or 0 <= num_cols <= 3:
hg_total = 0
hg_max_sum = 0
# There's hourglass
else:
if num_rows > num_cols:
# hg_total = num_cols - 2 + ( num_rows - num_cols )
hg_total = num_rows - 2
#elif num_cols > num_rows:
else:
# hg_total = num_rows - 2 + ( num_cols - num_rows )
hg_total = num_cols - 2
# irrelevant and could be added to any of the others, transforming the elif into else
# else:
# hg_total = num_rows - 2
# only one hourglass
if hg_total == 1:
# calculate hg_current_sum
row_1 = arr[0][0:3]
row_2 = arr[1][1]
row_3 = arr[2][0:3]
#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
"""
#print(f"row_1: {row_1}")
#print(f"row_2: {row_2}")
#print(f"row_3: {row_3}")
#output
"""
row_1: [1, 1, 1]
row_2: 1
row_3: [1, 1, 1]
"""
# Note that row_2 won't have sum() because it'll be always int and not a list of numbers
hg_current_sum = sum(row_1) + row_2 + sum(row_3)
hg_max_sum = hg_current_sum
return hg_max_sum
# Generalize
while i < num_rows:
row_1 = arr[i][0:3]
row_2 = arr[i+1][1]
row_3 = arr[i+2][0:3]
hg_current_sum = sum(row_1) + row_2 + sum(row_3)
# 9 is the highest value for a cell
# 7 is the amount of cells in each hourglass
# lowest_sum = -9 * 7
# Hightest_sum = 9 * 7
if hg_current_sum == 9*7:
hg_max_sum = hg_current_sum
break
elif hg_current_sum > hg_max_sum:
hg_max_sum = hg_current_sum
i = i + 2
while j < num_cols:
row_1 = arr[0][j:j+2]
row_2 = arr[1][j+1]
row_3 = arr[2][j:j+2]
hg_current_sum = sum(row_1) + row_2 + sum(row_3)
# 9 is the highest value for a cell
# 7 is the amount of cells in each hourglass
# lowest_sum = -9 * 7
# Hightest_sum = 9 * 7
if hg_current_sum == 9*7:
hg_max_sum = hg_current_sum
break
elif hg_current_sum > hg_max_sum:
hg_max_sum = hg_current_sum
j = j + 2
return hg_max_sum
If I execute this, it will give a
Error (stderr) Traceback (most recent call last): File
"Solution.py", line 119, in
result = hourglassSum(arr) File "Solution.py", line 74, in hourglassSum
row_3 = arr[i+2][0:3] IndexError: list index out of range
The problem I'm having is in the generalization of the behaviour, from the comment # Generalize
onwards. That moment onwards, starts the scenario of more than one hourglasses.
I can see how the movement of the hourglass should happen: top left -> top right (moving 1 cell to the right until the furthest right cell in the hourglass reaches the last existing column in the array) and repeat this process moving 1 cell down until the furthest down cell in the hourglass reaches the last row / bottom of the array.
Can see it could be done with a for loop (going from left -> right) inside of a for loop (going from top -> bottom). So, something like
for i in range(num_rows)
# do stuff
for j in range(num_cells)
# do stuff
This would ofc make the part within loops nearly unnecessary; the only reason I have them here is to visualize the movement of each cell to the right or to the bottom.
What then?
Moving to the right, I would update each part of the hourglass as a "sliding window," subtracting the former leftmost element and adding the new rightmost element. Start a new hourglass when moving the hourglass down a row.
Here's JavaScript code, easily convertable to Python:
function f(m){ if (m.length < 3 || m[0].length < 3) return null; let row1, row2, row3; let best = -Infinity; for (let i=0; i<m.length-2; i++){ // Update the hourglass moving down row1 = m[i][0] + m[i][1] + m[i][2]; row2 = m[i+1][1]; row3 = m[i+2][0] + m[i+2][1] + m[i+2][2]; best = Math.max(best, row1 + row2 + row3); for (let j=1; j<m[0].length-2; j++){ // Update the hourglass moving to the right row1 += m[i][j+2] - m[i][j-1]; row2 = m[i+1][j+1]; row3 += m[i+2][j+2] - m[i+2][j-1]; best = Math.max(best, row1 + row2 + row3); } } return best; } var m = [ [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] ]; console.log(f(m));
and here's the Python code:
def hourglassSum(arr):
#print(f"arr: {arr}")
#print(f"arr[1]: {arr[1]}")
#print(f"arr[1][1]: {arr[1][1]}")
num_rows = len(arr)
num_cols = len(arr[0])
hg_max_sum = -float('Inf') #-inf
hg_current_sum = 0
i = 0
j = 1
# There's no hourglass
if 0 <= num_rows <= 3 or 0 <= num_cols <= 3:
hg_max_sum = 0
for i in range(0,num_rows - 2):
# Update the hourglass moving down
row1 = arr[i][0] + arr[i][1] + arr[i][2];
row2 = arr[i+1][1];
row3 = arr[i+2][0] + arr[i+2][1] + arr[i+2][2];
hg_current_sum = row1 + row2 + row3
#print(f"1_ hg_current_sum: {hg_current_sum}")
hg_max_sum = max(hg_max_sum, hg_current_sum);
#print(f"1_ hg_max_sum: {hg_max_sum}")
for j in range(1,num_cols - 2):
# Update the hourglass moving to the right
row1 += arr[i][j+2] - arr[i][j-1];
row2 = arr[i+1][j+1];
row3 += arr[i+2][j+2] - arr[i+2][j-1];
hg_current_sum = row1 + row2 + row3
#print(f"2_ hg_current_sum: {hg_current_sum}")
hg_max_sum = max(hg_max_sum, hg_current_sum);
#print(f"2_ hg_max_sum: {hg_max_sum}")
return hg_max_sum
basically the difference is that now
This will pass all the current tests
public static int hourglassSum(List<List<int>> arr)
{
int[] sum = new int[16];
int hourglass = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
sum[hourglass] =
arr[i][j] + arr[i][j + 1] + arr[i][j + 2]
+ arr[i + 1][j + 1]
+ arr[i + 2][j] + arr[i + 2][j + 1] + arr[i + 2][j + 2];
hourglass++;
}
}
return sum.Max();;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.