问题描述
我有一个长度为 size * size
的一维数组,代表值的正方形字段。
我的目标是旋转数组()。我目前在获取正确的内圈索引方面遇到问题。我的算法有什么错误?
I have a 1D array of length size * size
, representing a square field of values.My goal is to rotate the array in place (previous question). I currently have issues getting the correct index in the inner rings. What is the mistake in my algorithm?
这是我的代码,请跳过下面的说明&示例。
This is my code, skip below for an explanation & examples.
fn rotate_square_slice<T>(slice: &mut [T], size: usize) {
for r in 0..(size + 1) / 2 {
// current ring side length
let l = size - 1 - r;
for i in r..l {
let a = size * r + r+i ;
let b = size * (r+i) + l-r ;
let c = size * (l-r) + l-r-i;
let d = size * (l-r-i) + r ;
slice.swap(a, b);
slice.swap(a, c);
slice.swap(a, d);
}
}
}
说明
Explanation
array = [A, B, C, D, E,
A, B, C, D, E,
A, B, C, D, E,
A, B, C, D, E,
A, B, C, D, E]
ring 0: | symmetries:
|
A B C D E | A . . . E . B . . . . . C . .
A . . . E | . . . . . . . . . E . . . . .
A . . . E | . . . . . + . . . . . + A . . . E + etc...
A . . . E | . . . . . A . . . . . . . . .
A B C D E | A . . . E . . . D . . . C . .
ring 1: | symmetries:
|
. . . . . | . . . . . . . . . .
. B C D . | . B . D . . . C . .
. B . D . | . . . . . . B . D .
. B C D . | . B . D . . . C . .
. . . . . | . . . . . . . . . .
示例迭代步骤
Example Iteration Step
0 1 2 3 4
0 . a . . .
1 . . . . b
2 . . . . .
3 d . . . .
4 . . . c .
size = 5 | position(a) = ( r , r+i ) = (0, 1)
r = 0 | position(b) = ( r+i , l-r ) = (1, 4)
l = 4 | position(c) = ( l-r , l-r-i) = (4, 3)
i = 1 | position(d) = (l-r-i, r ) = (3, 0)
示例输出
在5 * 5正方形数组上使用一维索引,这是所有索引元组(a,b,c,d)的期望输出和当前输出:
Example Output
Using 1D-indexing on a 5*5 "square" array, here are the desired and current output of all tuples of indices (a, b, c, d):
desired output | current output | parameters
| | r l i
( 0, 4, 24, 20) | ( 0, 4, 24, 20) | 0 4 0
( 1, 9, 23, 15) | ( 1, 9, 23, 15) | 0 4 1
( 2, 14, 22, 10) | ( 2, 14, 22, 10) | 0 4 2
( 3, 19, 21, 5) | ( 2, 14, 22, 10) | 0 4 3
| |
( 6, 8, 18, 16) | ( 7, 12, 11, 6) | 1 3 1 <- mistake
( 7, 13, 17, 11) | ( 8, 17, 10, 1) | 1 3 2 <- mistake
| |
我希望ASCII插图有助于演示我想要的内容。如果需要澄清,请告诉我。
I hope the ASCII illustrations help to demonstrate what I want. If clarification is needed, please let me know.
推荐答案
问题是由使用 l引起的
元素的位置与环,尺寸和尺寸直接相关。索引,但不是当前环( l
)上有多少个唯一索引。这是我在原始代码中的错误。
The issue was caused by using l
in the calculations at all.
An element's position is directly related to the ring, size & index, but not to how many unique indices there are on the current ring (l
). This was my mistake in the original code.
如@Gene在评论中所述,旋转 i
'在 i
步的左边排,在 j
'ths的列向下排 j
步骤,可以获得类似的结果。我仍然相信,我在下面介绍的方法有其优点,因为可以轻松扩展它,以允许对要旋转的元组进行任意条件检查。
As mentioned by @Gene in the comments, rotating the i
'ths row left by i
steps and the j
'ths column down by j
steps, one could achieve a similar result. I still believe that the approach I present below has its merits, as it can be easily extended to allow for arbitrary condition checks on what tuples of elements to rotate.
enum Rotation {
Clockwise,
Counterclockwise,
}
fn rotate_square_slice<T>(slice: &mut [T], s: usize, rotation: Rotation) {
// iterate ringwise, from outer to inner
// skip center when size % 2 == 1
for r in 0..s / 2 {
// for all unique indices under rotational symmetry ...
for i in 0..s - (2 * r) - 1{
// ... get their 4 corresponding positions ...
let a = s * ( r ) + r+i ;
let b = s * ( r+i ) + s-r-1 ;
let c = s * ( s-r-1 ) + s-r-i-1 ;
let d = s * (s-r-i-1) + r ;
//... and swap them in the correct direction.
match rotation {
Rotation::Clockwise => {
slice.swap(a, b);
slice.swap(a, c);
slice.swap(a, d);
},
Rotation::Counterclockwise => {
slice.swap(a, b);
slice.swap(c, d);
slice.swap(b, d);
}
}
}
}
}
非常感谢@Jmb!
由于切片的线性布局,使用 chunks()
。整洁!
Because of the slice's linear layout, it is easy to just rotate a subslice of some Vec by using chunks()
. Neat!
这篇关于一维“正方形”中的旋转对称索引数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!