【问题标题】:Rotating rectangular array by 45 degrees将矩形阵列旋转 45 度
【发布时间】:2012-11-24 22:59:30
【问题描述】:

假设:

2D array:  abcdef
           ghijkl
           mnopqr

存储在简单的长宽*高字符串中,因此,我们称之为arr。

arr = abcdefghijklmnopqr
width = 6
height = strlen ( arr ) / width

目标是将此数组旋转 45 度 (PI/4) 并得到以下结果:

arr = abgchmdinejofkplqr
width = 3
height = 8
converted to 2D array:  a..
                        bg.
                        chm
                        din
                        ejo
                        fkp
                        .lq
                        ..r

我花了几个小时试图弄清楚如何进行这种转换,并提出了一些半功能性的解决方案,但我无法让它完全发挥作用。你能描述/写一个算法来解决这个问题吗?最好在C中。

感谢您的帮助

编辑:这是我已经尝试过的
Edit2: 45度旋转的目的是将对角线变成线,以便可以使用strstr搜索。

// this is 90 degree rotation. pretty simple
for ( i = 0; i < width * height; i++ ) {
  if ( i != 0 && !(i % height) ) row++;
  fieldVertical[i] = field[( ( i % height ) * width ) + row];
}   

// but I just can't get my head over rotating it 45 degrees. 
// this is what I've tried. It works untile 'border' is near the first edge.

row = 0;
int border = 1, rowMax = 0, col = 0; // Note that the array may be longer
// than wider and vice versa. In that case rowMax should be called colMax.

for ( i = 0; i < width * height; ) { 
  for ( j = 0; j < border; j++, i++ ) {
    fieldCClockwise[row * width + col] = field[i];
    col--;
    row++;
  }

  col = border;
  row = 0;
  border++;
}

我的代码中的“边界”是一个虚构的边界。在源代码中,它是对角线 分隔对角线的线。结果,这将是一条水平线 每一行。

1   2   3 / 4   5
6   7 / 8   9   10
11 /12  13  14  15

那些斜线是我们的分界线。 该算法应该非常简单,只需阅读 riagonals: 第一个数字 1,然后是 2,然后是 6,然后是 3,然后是 7,然后是 11,然后是 4,依此类推。

【问题讨论】:

  • 你是顺时针旋转还是逆时针旋转?
  • 请展示您的尝试
  • 我需要同时做这两个,但是一旦我有一个算法来旋转它,另一种方式将是相似的。
  • 当您说“旋转”时,您的意思是更像“倾斜”吗? “a”在旋转后保持在同一个位置。
  • 是的,'a' 保持在同一个位置。我实际上需要将对角线变成线,以便我可以使用 strstr 搜索对角线。

标签: c arrays algorithm


【解决方案1】:

我查看了http://en.wikipedia.org/wiki/Shear_mapping 的灵感并生成了这个 python 代码:

a = [['a', 'b', 'c', 'd', 'e', 'f'],
     ['g', 'h', 'i', 'j', 'k', 'l'],
     ['m', 'n', 'o', 'p', 'q', 'r']]

m = 1 # 1/m = slope

def shear_45_ccw(array):
    ret = []
    for i in range(len(array)):
        ret.append([0] * 8)
        for j in range(len(array[i])):
            ret[i][int(i + m * j)] = array[i][j]
    return ret

print(shear_45_ccw(a))

产生:

[['a', 'b', 'c', 'd', 'e', 'f', 0, 0], 
 [0, 'g', 'h', 'i', 'j', 'k', 'l', 0], 
 [0, 0, 'm', 'n', 'o', 'p', 'q', 'r']]

这就是你想要的。该算法希望是可读的,即使它在 python 中。它的核心是:ret[i][int(i + m * j)] = array[i][j]。祝你好运!我在初始化数组时作弊;无论如何,你必须在 C 中以不同的方式处理。

编辑:另外,我不知道为什么你的结果会被翻转等等:我相信你可以做出正确的行为。

【讨论】:

  • 谢谢,这看起来不错,如果我找不到更简单的解决方案,我会使用它。我试图避免使用二维数组,因为最终它必须转换回一维数组。
  • K,在一维数组中,如果你可以只跟踪索引(i,j),那么结果将转到i + i + j。
【解决方案2】:

我称之为对角线扫描,而不是旋转 45 度。

在您的示例中,对角线在左下方;我们可以枚举它们 1, 2, ...:

123456
234567
345678

这将是外循环迭代的计数器。内部循环将运行 1、2 或 3 次迭代。为了从一个编号符号跳到另一个,像你一样做col--; row++;,或者将width-1添加到一个线性索引中:

....5. (example)
...5..
..5...

代码(未经测试):

char *field;
int width = 6;
int height = 3;
char *field45 = malloc(width * height);
int diag_x = 0, diag_y = 0; // coordinate at which the diagonal starts
int x, y; // coordinate of the symbol to output
while (diag_y < height)
{
    x = diag_x; y = diag_y;
    while (x >= 0 && y < height) // repeat until out of field
    {
        *field45++ = field[y * width + x]; // output current symbol
        --x; ++y; // go to next symbol on the diagonal
    }
    // Now go to next diagonal - either right or down, whatever is possible
    if (diag_x == width - 1)
        ++diag_y;
    else
        ++diag_x;
}

如果您想在另一个方向“旋转”,您可能需要将代码周围的++ 更改为--,并可能将循环中的边界检查更改为相反。

此外,您可以将(x,y) 坐标替换为一个索引(将++y 替换为index+=width);为了清楚起见,我使用了(x,y)

【讨论】:

    【解决方案3】:

    我想通过上面的帮助并通过一个例子来解决这个问题:

    import pandas as pd
    import numpy as np
    bd = np.matrix([[44., -1., 40., 42., 40., 39., 37., 36., -1.],
                    [42., -1., 43., 42., 39., 39., 41., 40., 36.],
                    [37., 37., 37., 35., 38., 37., 37., 33., 34.],
                    [35., 38., -1., 35., 37., 36., 36., 35., -1.],
                    [36., 35., 36., 35., 34., 33., 32., 29., 28.],
                    [38., 37., 35., -1., 30., -1., 29., 30., 32.]])
    def rotate45(array):
        rot = []
        for i in range(len(array)):
            rot.append([0] * (len(array)+len(array[0])-1))
            for j in range(len(array[i])):
                rot[i][int(i + j)] = array[i][j]
        return rot
    
    df_bd = pd.DataFrame(data=np.matrix(rotate45(bd.transpose().tolist())))
    df_bd = df_bd.transpose()
    print df_bd

    其中的输出会是这样的:

    44   0   0   0   0   0   0   0   0
    42  -1   0   0   0   0   0   0   0
    37  -1  40   0   0   0   0   0   0
    35  37  43  42   0   0   0   0   0
    36  38  37  42  40   0   0   0   0
    38  35  -1  35  39  39   0   0   0
    0   37  36  35  38  39  37   0   0
    0    0  35  35  37  37  41  36   0
    0    0   0  -1  34  36  37  40  -1
    0    0   0   0  30  33  36  33  36
    0    0   0   0   0  -1  32  35  34
    0    0   0   0   0   0  29  29  -1
    0    0   0   0   0   0   0  30  28
    0    0   0   0   0   0   0   0  32

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-04
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      相关资源
      最近更新 更多