简体   繁体   中英

Swapping Elements of a Slice (in-place)

I have posted my solution in the answers below.

The question will not be updated with even more code to not further increase clutter.


I'm trying to rotate all elements in a Vec<Vec<T>> clockwise. The vector is guaranteed to be square, as in v.len() == v[0].len() .

The idea is to

  • find all elements that are equivalent under rotational symmetry to v 's center
  • swap these elements in place, using std::mem::swap

My current code does not change the state of the vec. How do I fix this?

fn rotate<T>(v: &mut Vec<Vec<T>>) {

    // swap elements equivalent to position i on each ring r 
    // limit l = side length of current ring
    //
    // + 0 - - - - +   r = 0 -> l = 6
    // | + 1 - - + |   r = 1 -> l = 4
    // | | + 2 + | |   r = 2 -> l = 2
    // | | |   | | |
    // | | + - + | |   swap:
    // | + - - - + |     a b c d
    // + - - - - - +   > b a c d
    //                 > c a b d
    //                 > d a b c

    for r in 0..((v.len() + 1) / 2 {
        let l = v.len() - 1 - r;
        for i in r..l {
            let mut a = & pieces[  r  ][ r+i ];
            let mut b = & pieces[ r+i ][ l-r ];
            let mut c = & pieces[ l-r ][l-r-i];
            let mut d = & pieces[l-r-i][  r  ];

            _rot_cw(&mut a, &mut b, &mut c, &mut d)},
        }
    }

    fn _rot_cw<T>(a: &mut T, b: &mut T, c: &mut T, d: &mut T) {
        //rotates a->b, b->c, c->d, d->a
        std::mem::swap(a, b);
        std::mem::swap(a, c);
        std::mem::swap(a, d);
    }
}

Edit:
Fixed minor issues in the original code above, thanks to @Jmb. Here's my current code, again running into borrowing issues:

fn rotate_square_slice<T>(slice: &mut Vec<T>, rows: usize) {
    for r in 0..(slice.len()+1)/2 {
        let l = slice.len() -1 - r;
        for i in r..l {
            let a = &mut slice.get_mut(rows *    r    +  r+i ).unwrap();
            let b = &mut slice.get_mut(rows *  (r+i)  +  l-r ).unwrap();
            let c = &mut slice.get_mut(rows *  (l-r)  + l-r-i).unwrap();
            let d = &mut slice.get_mut(rows * (l-r-i) +   r  ).unwrap();

            std::mem::swap(a, b);
            std::mem::swap(a, c);
            std::mem::swap(a, d);
        }
    }
}

Swapping elements in a slice can be done by using the slice's swap() method .

Solving that problem, the code now looks like this:

fn rotate_square_slice<T>(slice: &mut [T], size: usize) {
    for r in 0..(size + 1) / 2 {
        let l = size - 1 - r;
        for i in r..l {    
            // b, c & d are the indices with rotational symmetry to a,
            // shifted by 90°, 180° & 270° respectively
            
            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);
        }
    }
}

I have, however, run into an issue with correctly indexing the slice. The question can be found here:

Rotational Symmetry Indexing in a 1D "Square" Array

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM