一维“正方形”中的旋转对称索引数组 [英] Rotational Symmetry Indexing in a 1D "Square" Array

查看:113
本文介绍了一维“正方形”中的旋转对称索引数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个长度为 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!

这篇关于一维“正方形”中的旋转对称索引数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆