Search code examples
rmatrixvectorizationdiagonal

Generating 5x5 matrix given a vector and 0's lined anti-diagonally


Given only the following vector:

v <- c(2, 4, 6, 8)

The following matrix is desired in which the row-wise directions are alternately right-to-left and left-to-right (by traversing the matrix from top to bottom) and the anti-diagonal is set to zero.

8  6  4  2  0
2  4  6  0  8
8  6  0  4  2
2  0  4  6  8
0  8  6  4  2

How this can be accomplished efficiently in R?


Solution

  • How about this?

    v <- c(2, 4, 6, 8)
    

    First create a matrix with alternating directions of v. Because matrices are filled column-wise we have to transpose in the end.

    m <- matrix(0, length(v), length(v) + 1)
    m[, c(FALSE, TRUE)] <- rev(v)
    m[, c(TRUE, FALSE)] <- v
    
    m <- t(m)
    

    Now create the zero anti-diagonal by filling the upper and lower triangles and then reversing the columns:

    m1 <- matrix(0, length(v) + 1, length(v) + 1)
    m1[upper.tri(m1)] <- m[upper.tri(m, TRUE)]
    m1[lower.tri(m1)] <- m[lower.tri(m)]
    m1[, rev(seq_len(ncol(m1)))]
    
    #     [,1] [,2] [,3] [,4] [,5]
    #[1,]    8    6    4    2    0
    #[2,]    2    4    6    0    8
    #[3,]    8    6    0    4    2
    #[4,]    2    0    4    6    8
    #[5,]    0    8    6    4    2
    

    I expect this to be an efficient solution for vectors of a larger size. For small vectors loop-based solutions are possibly faster.