Hello everybody. I am trying to reproduce a particular matrix in an elegant way. If I have jj1 <- structure(c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2, 3,1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1,2,3, 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,3,1,2,3,1, 2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1, 2),.Dim = as.integer(c(9,9))) [ image(jj1) is good here ] then I can get this with kronecker(matrix(1,3,1),kronecker(1+outer(0:2,0:2,"+")%%3,matrix(1,1,3))) I want to reproduce the following matrices in an equivalent way: jj2 <- matrix(c(1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1, 1,2,3,1,2,3,1,2,3,3,1,2,3,1,2,3,1,2,1,2,3,1,2, 3,1,2,3,3,1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1,3, 1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1),9,9) jj3 <- structure(c(1,2,3,2,3,1,3,1,2,1,2,1,2,3,2,3,1, 3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1,2,3,2,3, 2,3,1,3,1,2,1,2,1,2,3,2,3,1,3,1,3,1,2,1,2, 3,2,3,1,3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1, 2),.Dim as.integer(c(9,9))) [ note that jj1-jj3 each have precisely 3 occurrences of A, B, and C along each row, column and (broken) diagonal ]. Can anyone give me a nice elegant way of creating jj2 and jj3 please? -- Robin Hankin Uncertainty Analyst Southampton Oceanography Centre SO14 3ZH tel +44(0)23-8059-7743 initialDOTsurname@soc.soton.ac.uk (edit in obvious way; spam precaution) [[alternative HTML version deleted]]
It's not obvious what pattern you want, but some variants of the following would work for jj1 and jj2: 1+outer(1:9, 1:9, "+")%%3 In particular the following are equal to your jj1 and jj2: jj1. <- 1+outer(0:8, rep(0:2, e=3), "+")%%3 jj2. <- 1+outer(0:8, c(1,2,1,3,1,3,2,3,2)-1, "+")%%3 I couldn't figure out jj3, but this system may not work so easily for that. hope this helps. spencer graves Robin Hankin wrote:>Hello everybody. > >I am trying to reproduce a particular matrix in an elegant way. If I >have > >jj1 <- >structure(c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2, >3,1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1,2,3, >1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,3,1,2,3,1, >2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1, >2),.Dim = as.integer(c(9,9))) > >[ image(jj1) is good here ] then I can get this with > >kronecker(matrix(1,3,1),kronecker(1+outer(0:2,0:2,"+")%%3,matrix(1,1,3))) > >I want to reproduce the following matrices in an equivalent way: > >jj2 <- matrix(c(1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1, >1,2,3,1,2,3,1,2,3,3,1,2,3,1,2,3,1,2,1,2,3,1,2, >3,1,2,3,3,1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1,3, >1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1),9,9) > >jj3 <- structure(c(1,2,3,2,3,1,3,1,2,1,2,1,2,3,2,3,1, >3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1,2,3,2,3, >2,3,1,3,1,2,1,2,1,2,3,2,3,1,3,1,3,1,2,1,2, >3,2,3,1,3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1, 2),.Dim >as.integer(c(9,9))) > >[ note that jj1-jj3 each have precisely 3 occurrences of A, B, and C >along each row, column and (broken) diagonal ]. > >Can anyone give me a nice elegant way of creating jj2 and jj3 please? > > >
Not sure if this qualifies as elegant or not but it (1) does allow one to generate all three matrices using the same scheme, (2) is simple requiring only a single one line function, (3) reduces the number of numbers you must specify from 81 to 18 per matrix and (4) gives some kminimal insight into the patterns. The key observation is that each row of each matrix is a cyclically shifted version of the first row of that same matrix. Thus given the first row and a vector of shifts we can reconstruct the remaining rows. Define a function which shifts its vector argument v by shift positions to the left producing a one row matrix. If shift is a vector the each row of the result corresponds to one shift in vector shift. shiftL <- function(v, shift) outer(shift,seq(along=v)-1, function(i,j)v[(i+j)%%length(v)+1]) # now run shiftL using the first row of each matrix and the shift vector # for each matrix jj1 <- shiftL(c(1,1,1,2,2,2,3,3,3),c(0,3,6,0,3,6,0,3,6)) jj2 <- shiftL(c(1,2,1,3,1,3,2,3,2),c(0,6,3,0,6,3,0,6,3)) jj3 <- shiftL(c(1,1,1,2,2,2,3,3,3),c(0,4,8,3,7,2,6,1,5)) or turning the input vectors into expressions themselves: jj1 <- shiftL( rep(1:3,c(3,3,3)), rep(c(0,3,6),3) ) jj2 <- shiftL( c(shiftL(c(1,3,2),c(0,2,0))), rep(c(0,6,3),3) ) jj3 <- shiftL( rep(1:3,c(3,3,3)), seq(0,32,4) %% 9 ) Robin Hankin <rksh <at> soc.soton.ac.uk> writes: : : Hello everybody. : : I am trying to reproduce a particular matrix in an elegant way. If I : have : : jj1 <- : structure(c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2, : 3,1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1,2,3, : 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,3,1,2,3,1, : 2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1, : 2),.Dim = as.integer(c(9,9))) : : [ image(jj1) is good here ] then I can get this with : : kronecker(matrix(1,3,1),kronecker(1+outer(0:2,0:2,"+")%%3,matrix(1,1,3))) : : I want to reproduce the following matrices in an equivalent way: : : jj2 <- matrix(c(1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1, : 1,2,3,1,2,3,1,2,3,3,1,2,3,1,2,3,1,2,1,2,3,1,2, : 3,1,2,3,3,1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1,3, : 1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1),9,9) : : jj3 <- structure(c(1,2,3,2,3,1,3,1,2,1,2,1,2,3,2,3,1, : 3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1,2,3,2,3, : 2,3,1,3,1,2,1,2,1,2,3,2,3,1,3,1,3,1,2,1,2, : 3,2,3,1,3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1, 2),.Dim : as.integer(c(9,9))) : : [ note that jj1-jj3 each have precisely 3 occurrences of A, B, and C : along each row, column and (broken) diagonal ]. : : Can anyone give me a nice elegant way of creating jj2 and jj3 please? :
[Sorry if this gets posted twice but I am having more gmane posting problems.] Not sure if this qualifies as elegant or not but it does (1) bring all three matrices under a single scheme, (2) reduce the number of numbers from 81 to 18 per matrix, (3) requires only a single one line utility function, (4) is simple and (5) gives some minimal insight into the patterns. The key thing to note is that each row of each matrix is a cyclic shift of the first row of that matrix. Define a shift function which shifts its vector argument v by shift positions to the left creating a one row matrix. If shift is a vector it creates a matrix with one row per shift. shiftL <- function(v, shift) outer(shift,seq(along=v)-1, function(i,j)v[(i+j)%%length(v)+1]) jj1a <- shiftL(c(1,1,1,2,2,2,3,3,3),c(0,3,6,0,3,6,0,3,6)) jj2a <- shiftL(c(1,2,1,3,1,3,2,3,2),c(0,6,3,0,6,3,0,6,3)) jj3a <- shiftL(c(1,1,1,2,2,2,3,3,3),c(0,4,8,3,7,2,6,1,5)) # or finding expressions for the two args in each case: jj1b <- shiftL( rep(1:3,c(3,3,3)), rep(c(0,3,6),3) ) jj2b <- shiftL( c(shiftL(c(1,3,2),c(0,2,0))), rep(c(0,6,3),3) ) jj3b <- shiftL( rep(1:3,c(3,3,3)), seq(0,32,4) %% 9 )
Robin Hankin wrote:> Hello everybody. > > I am trying to reproduce a particular matrix in an elegant way. If I > have > > jj1 <- > structure(c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2, > 3,1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1,2,3, > 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,3,1,2,3,1, > 2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1, > 2),.Dim = as.integer(c(9,9))) > > [ image(jj1) is good here ] then I can get this with > > kronecker(matrix(1,3,1),kronecker(1+outer(0:2,0:2,"+")%%3,matrix(1,1,3))) > > I want to reproduce the following matrices in an equivalent way: > > jj2 <- matrix(c(1,2,3,1,2,3,1,2,3,2,3,1,2,3,1,2,3,1, > 1,2,3,1,2,3,1,2,3,3,1,2,3,1,2,3,1,2,1,2,3,1,2, > 3,1,2,3,3,1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1,3, > 1,2,3,1,2,3,1,2,2,3,1,2,3,1,2,3,1),9,9) > > jj3 <- structure(c(1,2,3,2,3,1,3,1,2,1,2,1,2,3,2,3,1, > 3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1,2,3,2,3, > 2,3,1,3,1,2,1,2,1,2,3,2,3,1,3,1,3,1,2,1,2, > 3,2,3,1,3,1,3,1,2,1,2,3,2,3,2,3,1,3,1,2,1, 2),.Dim > as.integer(c(9,9))) >some musings. You have not told us hove jj3 arises naturally, but its structure seems to have something to do with magic squares. So library(magic) # on CRAN is.magic(jj3) # TRUE This is not in accordance with my concept of magic squares, since an n*n magic square should have all the numbers from 1 to n^2 exactly once. But all rowSums and colSums are equal. Note that if we view jj3 as a 3*3 block matrix, with each block a 3*3 matrix, then all the blockx are generated rowwise the following way: Let x in 1:3 be the generator, and + be sum modulo 3, but we take the rep 3 and not 0. Then we have x x x x+1 x+1 x+2 x+2 x x and the 3*3 matrix of the generators can be generated in the following way: > xx <- ((magic(3) %% 3)+1)[,3:1] > xx [,1] [,2] [,3] [1,] 1 2 3 [2,] 2 3 1 [3,] 3 1 2 > "++" <- function(x,a) { if ( (x+a)%%3 == 0 ) 3 else (x+a) %% 3 } > makeBlock <- function(x) { + matrix( c( rep(x,3), rep("++"(x,1), 2), rep("++"(x,2), 2), + rep(x,2) ) , 3,3, byrow=TRUE) } > makeBlock(1) [,1] [,2] [,3] [1,] 1 1 1 [2,] 2 2 3 [3,] 3 1 1 > ans <- matrix (NA,9,9) > for (i in 1:3) for (j in 1:3) { + ans[3*(i-1)+1:3, 3*(j-1)+1:3] <- makeBlock(xx[i,j]) } > ans [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [1,] 1 1 1 2 2 2 3 3 3 [2,] 2 2 3 3 3 1 1 1 2 [3,] 3 1 1 1 2 2 2 3 3 [4,] 2 2 2 3 3 3 1 1 1 [5,] 3 3 1 1 1 2 2 2 3 [6,] 1 2 2 2 3 3 3 1 1 [7,] 3 3 3 1 1 1 2 2 2 [8,] 1 1 2 2 2 3 3 3 1 [9,] 2 3 3 3 1 1 1 2 2 > ans ==jj3 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [2,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [3,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [4,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [5,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [6,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [7,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [8,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [9,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE Kjetil Halvorsen> [ note that jj1-jj3 each have precisely 3 occurrences of A, B, and C > along each row, column and (broken) diagonal ]. > > Can anyone give me a nice elegant way of creating jj2 and jj3 please? >
In reading this over I noticed that the two input vectors to shiftL could be put in a parameterized form that reduces the input to two integers: shiftL <- function(v, shift) outer(shift,seq(along=v)-1, function(i,j)v[(i+j)%%length(v)+1]) jj <- function(i,j) shiftL( seq(0,by=i,len=9) %% 9 %/% 3 + 1, seq(0, len=9, by=j) %% 9) jj1 <- jj(1,3) jj2 <- jj(5,6) jj3 <- jj(1,4) From: Gabor Grothendieck <ggrothendieck at myway.com> [Sorry if this gets posted twice but I am having more gmane posting problems.] Not sure if this qualifies as elegant or not but it does (1) bring all three matrices under a single scheme, (2) reduce the number of numbers from 81 to 18 per matrix, (3) requires only a single one line utility function, (4) is simple and (5) gives some minimal insight into the patterns. The key thing to note is that each row of each matrix is a cyclic shift of the first row of that matrix. Define a shift function which shifts its vector argument v by shift positions to the left creating a one row matrix. If shift is a vector it creates a matrix with one row per shift. shiftL <- function(v, shift) outer(shift,seq(along=v)-1, function(i,j)v[(i+j)%%length(v)+1]) jj1a <- shiftL(c(1,1,1,2,2,2,3,3,3),c(0,3,6,0,3,6,0,3,6)) jj2a <- shiftL(c(1,2,1,3,1,3,2,3,2),c(0,6,3,0,6,3,0,6,3)) jj3a <- shiftL(c(1,1,1,2,2,2,3,3,3),c(0,4,8,3,7,2,6,1,5)) # or finding expressions for the two args in each case: jj1b <- shiftL( rep(1:3,c(3,3,3)), rep(c(0,3,6),3) ) jj2b <- shiftL( c(shiftL(c(1,3,2),c(0,2,0))), rep(c(0,6,3),3) ) jj3b <- shiftL( rep(1:3,c(3,3,3)), seq(0,32,4) %% 9 )
Here is yet one more simplification. Note that seq9 in this one is not the same as seq9 in the last one. This one looks much more symmetric in the arguments and is shorter: seq9 <- function(i) seq(0, len = 9, by = i) jj <- function(i,j) outer( seq9(i), seq9(j), "+" ) %% 9 %/% 3 + 1 jj1. <- jj(3,1) jj2. <- jj(3,5) jj3. <- jj(4,1)