简体   繁体   English

概括二维阵列中的沙漏运动 - Python 中的 DS

[英]Generalize hourglass movement in 2D Array - DS in Python

While working through this HackerRank challenge to prepare for interviews, stumbled across a blocker.在通过这个 HackerRank 挑战为面试做准备时,偶然发现了一个障碍。

Basically want to create a function hourglassSum that should return an integer (the maximum hourglass sum in the array).基本上想创建一个 function hourglassSum,它应该返回一个 integer(数组中的最大沙漏总和)。 Given a 6 x 6 2D Array, arr:给定一个 6 x 6 二维数组,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. arr 中有 16 个沙漏,沙漏总和是沙漏值的总和。 In that case, the sum of an hourglass' is 7.在这种情况下,沙漏的总和为 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错误 (stderr) 回溯(最近调用最后一次):文件

"Solution.py", line 119, in “Solution.py”,第 119 行,在

result = hourglassSum(arr) File "Solution.py", line 74, in hourglassSum结果 = hourglassSum(arr) 文件“Solution.py”,第 74 行,在 hourglassSum 中

row_3 = arr[i+2][0:3] IndexError: list index out of range row_3 = arr[i+2][0:3] IndexError: 列表索引超出范围


The problem I'm having is in the generalization of the behaviour, from the comment # Generalize onwards.我遇到的问题是行为的泛化,从评论# Generalize开始。 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.我可以看到沙漏的移动方式:左上角 -> 右上角(向右移动 1 个单元格,直到沙漏中最右边的单元格到达数组中最后一个现有列)并重复此过程,向下移动 1 个单元格直到沙漏中最下方的单元格到达数组的最后一行/底部。

Can see it could be done with a for loop (going from left -> right) inside of a for loop (going from top -> bottom).可以看到它可以通过 for 循环(从顶部 -> 底部)内部的 for 循环(从左 -> 右)来完成。 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.向右移动,我会将沙漏的每个部分更新为“滑动 window”,减去之前最左边的元素并添加新的最右边元素。 Start a new hourglass when moving the hourglass down a row.将沙漏向下移动一行时开始一个新的沙漏。

Here's JavaScript code, easily convertable to Python:这是 JavaScript 代码,可轻松转换为 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));

Update by Tiago Martins Peres 李大仁: Tiago Martins Peres 李大仁更新:

and here's the Python code:这是 Python 代码:

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基本上不同的是现在

  • Removed some of the complexity you were adding by focusing in the essential通过关注基本要素,消除了您添加的一些复杂性
  • Made hg_max_sum as -inf将 hg_max_sum 设为 -inf
  • Used the for inside of the for where one moves down in the initial column (hence i = 0) and the other moves to the right and down (hence j = 1)使用 for 内部的 for,其中一个在初始列中向下移动(因此 i = 0),另一个向右和向下移动(因此 j = 1)
  • Removed ++i and ++j because the loop will increment it necessarily based on the given range删除了 ++i 和 ++j 因为循环将根据给定的范围必然增加它
  • Got right away the sum in each row_1, row_2 and row_3 (no need to store their real values) and associates it to a variable hg_current_sum立即得到每个 row_1、row_2 和 row_3 的总和(无需存储它们的真实值)并将其关联到变量 hg_current_sum
  • Uses the max() function to compare the highest value so far (hg_max_sum) with hg_current_sum使用 max() function 将迄今为止的最高值 (hg_max_sum) 与 hg_current_sum 进行比较

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();;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM