A way of amending multiple points in a square matrix in one go.
Take the following matrix:
q)4 4#0
(0 0 0 0;0 0 0 0;0 0 0 0;0 0 0 0)
Let's say we want to add 1 to the diagonal (make it the identity matrix). We could get ourselves a list of coordinates (0 0;1 1;2 2;3 3) and do it one at a time, using over to pass the previous result forward each time:
q).[;;+;1]/[4 4#0;(0 0;1 1;2 2;3 3)]
(1 0 0 0;0 1 0 0;0 0 1 0;0 0 0 1)
This would get pretty slow if the list of coordinates is large, since they are essentially scalar operations. So we can do as Arthur has done, flatten the matrix and use a bit of code to map the 2 dimensional coordinate to it's one dimensional equivalent:
q)(4*4)#0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
q)4 sv flip (0 0;1 1;2 2;3 3)
0 5 10 15
q)@[(4*4)#0;4 sv flip (0 0;1 1;2 2;3 3);+;1]
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1
The cut command gives us back the matrix from the flat vector:
q)4 cut @[(4*4)#0;4 sv flip (0 0;1 1;2 2;3 3);+;1]
(1 0 0 0;0 1 0 0;0 0 1 0;0 0 0 1)
2 comments:
Does not look like it's faster...
q)\t do [1000000;.[;;+;1]/[4 4#0;(0 0;1 1;2 2;3 3)]]
7234
q)\t do [1000000;4 cut @[(4*4)#0;4 sv flip (0 0;1 1;2 2;3 3);+;1]]
8218
has to be big enough to warrant it.
(0 0;1 1;2 2;3 3)
is too small, it's essentially atomic.
Post a Comment