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.

  • 1
    $\begingroup$ You may find this subsection of my book of interest. $\endgroup$ Mar 15, 2013 at 21:20
  • $\begingroup$ 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. $\endgroup$
    – Nick Name
    Mar 16, 2013 at 0:24
  • $\begingroup$ Nick, for the poker-hand problem I used Orderless myself. $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 6:35
  • $\begingroup$ @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. $\endgroup$
    – Nick Name
    Mar 16, 2013 at 10:41

1 Answer 1

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


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} *)
  • $\begingroup$ 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. $\endgroup$
    – Nick Name
    Mar 15, 2013 at 21:43
  • $\begingroup$ It can be done the way you want, but it's a bit more work. See the addendum. $\endgroup$ Mar 15, 2013 at 22:20
  • 1
    $\begingroup$ @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) $\endgroup$
    – rm -rf
    Mar 15, 2013 at 22:26
  • $\begingroup$ Wow. No idea. But I'm filing a bug report. $\endgroup$ Mar 15, 2013 at 22:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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