Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

first time stack exchange poster here! So I was working on a problem, the purpose of which was to write a function in the procedural style to rotate right the ith row of a matrix by i - 1 spaces. Ok, easy enough here was my implementation:

rotateRowsProcedural[mat_?MatrixQ] :=
(
  clonedMat = mat;
  i = 1;
  While[i <= Dimensions[clonedMat][[1]],
    clonedMat[[i]] = RotateRight[clonedMat[[i]], i - 1];
    i++;
  ];
  clonedMat
)

This was too boring so I decided I wanted to try and solve the problem using pattern matching approach and I came up with

rotateRowsPattern[matrix_?MatrixQ] := 
  matrix /. mat : {x__List} :> (RotateRight[#, Position[mat, #][[1, 1]] - 1] & /@ {x}) `

Now I thought this was pretty awesome I mean to me its the essence of Mathematica. However, I then decided to compare the efficiency of the two functions

Mean[Table[Timing[rotateRowsPattern[RandomInteger[{0, 10},{1000, 1000}]]][[1]], {100}]]

0.038844

Mean[Table[Timing[rotateRowsProcedural[RandomInteger[{0,10},{1000,1000}]]][[1]], {100}]]

0.0165361

I was surprised that the procedural implementation was faster. Then I thought it over and I think it is the case that calling Position in the pattern implementation must slow things down. My question then is if I want to use pattern matching how can I reference the location of x (from x__List) so that I don't have to call Position.

Also, I'm aware that combining Map and Range would be the most concise way to do this but I'm interested in the pattern matching.

share|improve this question
    
"Map and Range would be the most concise way..." - nope. There's MapIndexed[]... –  J. M. May 30 '13 at 6:00
    
This isn't using pattern matching but for a speed up this may help: rr[rin_] := (RotateRight[rin[[#]], # - 1] & /@ Range[Length[rin]]). –  Jonathan Shock May 30 '13 at 6:07
2  
I would also define your functions as Module as you are defining global variables (clonedmat) within them. It's best to keep track of the scope of such variables when you can. –  Jonathan Shock May 30 '13 at 6:09
    
@LarryS, please feel free to ignore my comment in that case. Not sure what the 'shit' is about. You are right that you did explicitly say that and I had missed that point in your post, my apologies. –  Jonathan Shock May 30 '13 at 6:22
6  
@LarryS Be civil. People are only attempting to be helpful. Leaving stray global symbols in your function is bad programming practice and code exhibiting such will often be remarked upon. –  Mr.Wizard May 30 '13 at 6:27
add comment

2 Answers

Since the summary of your question is:

My question then is if I want to use pattern matching how can I reference the location of x (from x__List) so that I don't have to call Position.

I believe it is a duplicate of: Position of a pattern-matched part of an expression

Nevertheless in an effort to be helpful I would like to comment on your code.

Your procedural function should use Module to localize the Symbols that you use. It would also be more efficient to calculate the dimensions only once:

rotateRowsProcedural[mat_?MatrixQ] := 
 Module[{clonedMat = mat, i = 1, dims = Dimensions[mat][[1]]},
  While[i <= dims, clonedMat[[i]] = RotateRight[clonedMat[[i]], i - 1]; i++;];
  clonedMat
 ]

Your pattern based function is a bit confusing. The pattern matching is purely incidental to the operation of the function itself which could be written simply:

rotateRowsPattern[matrix_?MatrixQ] := 
 RotateRight[#, Position[matrix, #][[1, 1]] - 1] & /@ matrix

But both this function and yours will fail of there are repeated rows in the matrix.

You will see from the linked question above that there is no known easy and general solution to the problem of getting the position of a matched pattern. However, for this simple application you can simply increment a counter for each row that is matched, which is perhaps in the spirit of what you intend:

rotateRows1[m_?MatrixQ] :=
  Module[{i = 0}, m /. x_?VectorQ :> RotateRight[x, i++]]

Still, this might be better formulated without the pattern matching as:

rotateRows2[m_?MatrixQ] := Module[{i = 0}, RotateRight[#, i++] & /@ m]

But this is really nothing more than a manual implementation of MapIndexed:

rotateRows3[m_?MatrixQ] := MapIndexed[RotateRight[#, #2[[1]] - 1] &, m]
share|improve this answer
    
One could of course do Length[mat] instead of Dimensions[mat][[1]]. Using While[] here looks a bit clunky; I'd have used Do[] myself. –  J. M. May 30 '13 at 6:39
    
@J.M. Agreed. I was attempting to work with the OP's style, for what it's worth. –  Mr.Wizard May 30 '13 at 6:55
    
@Mr.Wizard (of Oz) thanks for the link. I'm somewhat disappointed that matched elements from the pattern matcher don't know by default their position but thus is life. –  John Smith May 30 '13 at 15:16
add comment

You could consider using MapIndexed just to "tag" each row with its row number and then use a replacement rule from there:

rot[mat_] := MapIndexed[List, mat] /. {x_, i_} :> RotateRight[x, i - 1]

Faster, but less readable, is to use Transpose and Range instead of MapIndexed:

rot[mat_] := Transpose[{mat, Range@Length@mat}] /. {x_, i_} :> RotateRight[x, i - 1]
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.