Barry Ervin
Barry Ervin

Reputation: 43

Algorithm for rotating image represented by array not working as expected

I am trying to rotate the image (a) by making the values at "a" coordinates map to the rotated image according to the coordinates listed below. Why does this not work?

a = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

// Desired result: 
//  rotateImage(a) =
//     [[7, 4, 1],
//      [8, 5, 2],
//      [9, 6, 3]]

// aCoords =  [[00,01,02],
//             [10, 11, 12],
//             [20,21,22]]

// rotatedImageCoordsRelatingToa = [[20, 10, 00],
//                                     [21, 11, 01],
//                                     [22,12,02]]

function rotateImage(a) {
const image = [...a]
const length = a.length
const rotatedImage = [...a]
for(let i=0;i<length;i++){
    for(let j=0;j<length;j++){
        let toRotateCoord = length-(1+j)
        console.log("Original coordinates:" + i,j + " should map to rotated coordinates:"+ toRotateCoord, i)
        rotatedImage[i][j] = image[toRotateCoord][i]
    }
}
return rotatedImage;
}

rotateImage(a);

When I run this I get

//[[7,4,7], 
// [8,5,4], 
// [9,4,7]]
// Not
//     [[7, 4, 1],
//      [8, 5, 2],
//      [9, 6, 3]]

I know there is probably a better algorithm for this but I am curious why this approach is not working. It seems to be something with how the arrays are being accessed.

Upvotes: 1

Views: 106

Answers (2)

trincot
trincot

Reputation: 349964

The problem is that although rotatedImage = [...a] creates a new array, it does not create new subarrays. So, rotatedImage shares its rows with image. Whatever you assign to rotatedImage[i][j] will mutate the rows in image, affecting the result of some of the next assignments.

To avoid this, initialise rotatedImage as:

const rotatedImage = Array.from({length}, _ => []);

... and your code will work.

BTW: you don't need the image variable. Since you don't intend to mutate it, you can just use a.

function rotateImage(a) {
    const length = a.length;
    const rotatedImage = Array.from({length}, _ => []);
    for (let i = 0; i < length; i++) {
        for (let j = 0; j < length; j++) {
            rotatedImage[i][j] = a[length - (1 + j)][i];
        }
    }
    return rotatedImage;
}

let a = [[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]];
let b = rotateImage(a);
for (let row of b) console.log(row+"")

Upvotes: 2

Barry Ervin
Barry Ervin

Reputation: 43

As Cris Luengo mentioned, it appears that using the spread operator to assign rotatedImage still points to the same location in memory. I added a for loop to create the new array and now it works:

a = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

rotateImage(a);

function rotateImage(a) {
const image = [...a]
const length = a.length
const rotatedImage = []

for(var i = 0; i < length; i++){
        rotatedImage.push([]);
    };

for(let i=0;i<length;i++){
    for(let j=0;j<length;j++){
        let toRotateCoord = length-(1+j)
        rotatedImage[i][j] = image[toRotateCoord][i]
    }
}
return rotatedImage;
}

Upvotes: 3

Related Questions