Arrays 1D中的旋转对称索引;“正方形”;排列

Arrays 1D中的旋转对称索引;“正方形”;排列,arrays,algorithm,rust,rotation,Arrays,Algorithm,Rust,Rotation,我有一个长度为1D的数组size*size,表示一个值的正方形字段。 我的目标是将阵列旋转到位()。我目前在获取内环中的正确索引时遇到问题。我的算法有什么错误 这是我的代码,请跳过下面的解释和示例 代码(1.41.0) 示例迭代步骤 示例输出 在5*5“正方形”数组上使用1D索引,以下是所有索引元组(a、b、c、d)的所需和当前输出: 所需输出|电流输出|参数 || r l i ( 0, 4, 24, 20) | ( 0, 4, 24, 20) | 0 4 0 ( 1, 9, 23,

我有一个长度为1D的数组
size*size
,表示一个值的正方形字段。 我的目标是将阵列旋转到位()。我目前在获取内环中的正确索引时遇到问题。我的算法有什么错误

这是我的代码,请跳过下面的解释和示例

代码(1.41.0) 示例迭代步骤 示例输出 在5*5“正方形”数组上使用1D索引,以下是所有索引元组(a、b、c、d)的所需和当前输出:

所需输出|电流输出|参数
|| 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该问题完全是由于在计算中使用
l
引起的。 元素的位置与环、大小和索引直接相关,但与当前环上有多少唯一索引无关(
l
)。这是我在原始代码中的错误

正如@Gene在评论中提到的,将
i
左边的第行旋转
i
步,将
j
列向下旋转
j
步,可以获得类似的结果。我仍然相信我下面介绍的方法有其优点,因为它可以很容易地扩展,允许对要旋转的元素元组进行任意条件检查

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);
                }
            }
        }
    }
}
枚举旋转{
顺时针方向的
逆时针方向的
}
fn旋转\平方\切片(切片:&mut[T],s:usize,旋转:旋转){
//从外到内循环
//当大小%2==1时跳过中心
对于0..s/2{
//对于旋转对称下的所有唯一指数。。。
对于0..s-(2*r)-1中的i{
//…获取他们的4个对应位置。。。
设a=s*(r)+r+i;
设b=s*(r+i)+s-r-1;
设c=s*(s-r-1)+s-r-i-1;
设d=s*(s-r-i-1)+r;
//…并按正确的方向交换。
比赛轮换{
旋转::顺时针=>{
切片交换(a,b);
切片交换(a,c);
切片交换(a,d);
},
旋转::逆时针=>{
切片交换(a,b);
切片交换(c,d);
切片交换(b,d);
}
}
}
}
}
非常感谢@Jmb!看不见树林,看不见树木

由于切片的线性布局,只需使用旋转某个Vec的子切片即可。干净利落

该问题是由于在计算中使用了
l
。 元素的位置与环、大小和索引直接相关,但与当前环上有多少唯一索引无关(
l
)。这是我在原始代码中的错误

正如@Gene在评论中提到的,将
i
左边的第行旋转
i
步,将
j
列向下旋转
j
步,可以获得类似的结果。我仍然相信我下面介绍的方法有其优点,因为它可以很容易地扩展,允许对要旋转的元素元组进行任意条件检查

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);
                }
            }
        }
    }
}
枚举旋转{
顺时针方向的
逆时针方向的
}
fn旋转\平方\切片(切片:&mut[T],s:usize,旋转:旋转){
//从外到内循环
//当大小%2==1时跳过中心
对于0..s/2{
//对于旋转对称下的所有唯一指数。。。
对于0..s-(2*r)-1中的i{
//…获取他们的4个对应位置。。。
设a=s*(r)+r+i;
设b=s*(r+i)+s-r-1;
设c=s*(s-r-1)+s-r-i-1;
设d=s*(s-r-i-1)+r;
//…并按正确的方向交换。
比赛轮换{
旋转::顺时针=>{
切片交换(a,b);
切片交换(a,c);
切片交换(a,d);
},
旋转::逆时针=>{
切片交换(a,b);
切片交换(c,d);
切片交换(b,d);
}
}
}
}
}
非常感谢@Jmb!看不见树林,看不见树木


由于切片的线性布局,只需使用旋转某个Vec的子切片即可。干净利落

我猜我在处理环边长度l时犯了一个错误。不过,我不能用手指去碰它。它看起来像是你在减法
r
太多次了:当你计算
l
时减法一次,然后每次使用它时再减法一次(如
l-r
)。把你所有的
l-r
换成可能是直的
l
@Jmb。第一个元组的第一个值也是错误的(7而不是6),并且第一个值的公式不包含“l”。你有什么想法吗?是的:
i
r
开始,而不是从0开始。因此,您也应该将所有的
i+r
替换为普通的
i
(而
-i-r
替换为
-i
)。@Jmb谢谢。就在那里。我的错误是从0开始计算。如果我没弄错的话,你的版本几乎可以正常工作,除了案例c。我现在不在计算机附近,但稍后将尝试实施更改。非常感谢,真的!我猜我在处理环边长度l时犯了一个错误。不过,我不能用手指去碰它。它看起来像是你在减法
r
太多次了:当你计算
l
时减法一次,然后每次使用它时再减法一次(如
l-r
)。将所有
l-r
替换为
   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)
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
                 |                  |
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);
                }
            }
        }
    }
}