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.

I would like to generate sets of replacement rules programatically for predefining some permutations. So a function

MakeRule[cycles_List (* permute cycles *), n_Integer (* rule length *)]`

called as

MakeRule[{{2,3}}, 4]

will generate

{e1_, e2_, e3_, e4_} -> {e1, e3, e2, e4}

For the permutations, I have

Permute[l, Cycles[cycles]]

but I cannot find a way of generating the list of patterns. Something subscripted or indexed would be nice as per the example. I have tried:

1) Pattern[Subscript[e, 1], Blank[]]
2) Pattern[Symbol["e1"], Blank[]]
3) Pattern[e[[1]], Blank[]]

I have a feeling I am missing something obvious.

Edit: Apologies for an oversight on my part. The second pattern example works correctly while the first and third do not. Thanks to all who responded.

share|improve this question
1  
You may find this subsection of my book of interest. –  Leonid Shifrin Mar 15 '13 at 21:20
    
I went through a similar exercise looking at hashing algorithms for seven card poker hands. As the suit and rank sizes are fixed, I did the patterns by hand and let Permutations do the heavy lifting. –  Nick Name Mar 16 '13 at 0:24
    
Nick, for the poker-hand problem I used Orderless myself. –  Mr.Wizard Mar 16 '13 at 6:35
    
@Mr.W, indeed, a handy shortcut for the actual hash. Specifically, I was counting the permuted patterns to check I'd got the binomial coefficients right for the probabilities, and then per draw permuted integer partition counts for the rank encoding. –  Nick Name Mar 16 '13 at 10:41

1 Answer 1

up vote 6 down vote accepted
makeRule[e_, cycles_List , n_Integer] := Module[
  {vals = Table[Unique[ToString[e]], {n}]},
  Map[Pattern[#, Blank[]] &, vals] -> Permute[vals, Cycles[cycles]]
  ]

Example:

makeRule[e, {{2, 3}}, 4]

(* Out[307]= {e365_, e366_, e367_, e368_} -> {e365, e367, e366, e368} *)

With a bit more work we can get the sequential symbols starting at 1.

--- addendum ---

makeRule2[e_, cycles_List , n_Integer] := Module[
  {vals, estr = ToString[e]},
  vals = Table[ToExpression[StringJoin[estr, ToString[j]]], {j, n}];
  Map[Pattern[#, Blank[]] &, vals] -> Permute[vals, Cycles[cycles]]
  ]

In[309]:= makeRule2[e, {{2, 3}}, 4]

(* Out[309]= {e1_, e2_, e3_, e4_} -> {e1, e3, e2, e4} *)
share|improve this answer
    
Thanks - so a symbol has to be created to use in the pattern? It would be nice to index from 1, but this does the job. –  Nick Name Mar 15 '13 at 21:43
    
It can be done the way you want, but it's a bit more work. See the addendum. –  Daniel Lichtblau Mar 15 '13 at 22:20
1  
@DanielLichtblau I naïvely thought one could do Block[{$ModuleNumber = 1}, Unique["x"]] for the addendum, but... what happened was not pretty: Mathematica has detected an internal error: vMessage ENULL (v9). However, it doesn't crash in v7 and v8 (displays a warning). Any thoughts on why that happened? My guess would be that $ModuleNumber is critical to several internal routines and this messed with it and it cannot be Locked either, since it needs to be incremented. But somehow I don't think that's right (and I'm not convinced by my explanation) –  rm -rf Mar 15 '13 at 22:26
    
Wow. No idea. But I'm filing a bug report. –  Daniel Lichtblau Mar 15 '13 at 22:33
    
Thanks for filing :) –  rm -rf Mar 15 '13 at 22:37

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.