Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unsort: remembering a permutation and undoing it

Suppose I have a function f that takes a vector v and returns a new vector with the elements transformed in some way. It does that by calling function g that assumes the vector is sorted. So I want f to be defined like so:

f[v_] := Module[{s, r},
  s = Sort[v];  (* remember the permutation applied in order to sort v *)
  r = g[s];
  Unsort[r]     (* apply the inverse of that permutation *)
]

What's the best way to do the "Unsort"?

Or could we get really fancy and have this somehow work:

answer = Unsort[g[Sort[v]]];

ADDED: Let's make this concrete with a toy example. Suppose we want a function f that takes a vector and transforms it by adding to each element the next smallest element, if any. That's easy to write if we assume the vector is sorted, so let's write a helper function g that makes that assumption:

g[v_] := v + Prepend[Most@v, 0]

Now for the function we really want, f, that works whether or not v is sorted:

f[v_] := (* remember the order; 
            sort it;
            call g on it;
            put it back in the original order;
            return it
         *)
like image 950
dreeves Avatar asked Dec 28 '10 10:12

dreeves


1 Answers

One possible method:

 mylist = {c, 1, a, b, 2, 4, h, \[Pi]}
    g /@ (Sort@mylist)[[Ordering@Ordering@mylist]]

gives

{g[c], g1, g[a], g[b], g[2], g[4], g[h], g[[Pi]]}

That is,

(Sort@mylist)[[Ordering@Ordering@mylist]] == mylist

I originally learned of the above from MathGroup, [EDITED] from a post by Andrzej Kozlowski

http://forums.wolfram.com/mathgroup/archive/2007/Jun/msg00920.html

like image 158
681234 Avatar answered Oct 11 '22 17:10

681234