假设:
2D array: abcdef
ghijkl
mnopqr
存储在长度为* height的简单字符串中,因此,我们称之为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.
中感谢您的帮助
编辑:这是我已经尝试过的 编辑2: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++;
}
我的代码中的'border'是一个虚构的边界线。在源头,它是一个对角线 分隔对角线的线。在结果中,它将是一条水平线 每一行。
1 2 3 / 4 5
6 7 / 8 9 10
11 /12 13 14 15
这些斜线是我们的边界线。 该算法应该非常简单,只需阅读riagonals: 第一个数字1,然后是2,然后是6,然后是3,然后是7,然后是11,然后是4,依此类推。
答案 0 :(得分: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]
。祝好运!我在初始化阵列时作弊;无论如何,你必须以不同的方式处理它。
答案 1 :(得分:1)
我称之为对角扫描,而不是旋转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)
。
答案 2 :(得分:0)
我想借助上述内容并通过一个例子来解决这个问题:
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