2010-12-28 17 views
5

Supongamos que tengo una función f que toma un vector v y devuelve un nuevo vector con los elementos transformados de alguna manera. Lo hace llamando a la función g que supone que el vector está ordenado. Así que quiero f para definirse así:Desoriente: recordar una permutación y deshacerla

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 *) 
] 

¿Cuál es la mejor manera de hacer el "Desordenar"?

O podríamos obtener realmente de lujo y tienen esto de alguna manera funciona:

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

añadido: Vamos a hacer este hormigón con un ejemplo de juguete. Supongamos que queremos una función f que toma un vector y lo transforma añadiendo a cada elemento el siguiente elemento más pequeño, si lo hay. Eso es fácil escribir si asumimos el vector está ordenada, por lo que vamos a escribir una función auxiliar g que hace que esa suposición:

g[v_] := v + Prepend[[email protected], 0] 

Ahora para la función que realmente queremos, f, que funciona o no v se ordena :

f[v_] := (* remember the order; 
      sort it; 
      call g on it; 
      put it back in the original order; 
      return it 
     *) 

Respuesta

2

gracias a Tomd y Yaroslav, aquí es probablemente la forma más concisa/elegante de hacerlo:

f[v_] := g[[email protected]][[[email protected]@v]] 

y gracias a Janus, aquí hay un quizás más effic ient manera:

f[v_] := With[{o = [email protected]}, g[v[[o]]][[[email protected]]]] 

Tenga en cuenta que lo hace 2 tipos en lugar de 3.

Para la posteridad, aquí está mi intento original, aunque no creo que tenga nada que recomendaría a los anteriores:

f[v_] := With[{o = Ordering[v]}, Sort[Transpose[{o,g[v[[o]]]}]][[All,-1]]] 

Para abordar belisarius en los comentarios, la razón por la que no paso g como parámetro es porque estoy pensando en g como una función auxiliar para f. Es como si tuviera una función f que sería más fácil de escribir si pudiera asumir que su argumento era un vector ordenado. Así que escribo la versión que asume eso y luego hago este truco de envoltura.

+1

Tal vez sea mejor que pasar ** g ** como un parámetro. –

+1

o ligeramente más eficiente, cambiar su original al 'Con [{o = pedidos [v]}, Parte [g [v [[o]]]], para pedidos [o]]] '. – Janus

6

Un posible método:

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

da

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

Esto es,

([email protected])[[[email protected]@mylist]] == mylist 

originalmente supe de la arriba del grupo matemático, [Editado] a partir de un mensaje por Andrzej Kozlowsk i

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

+1

Ordenar^(2n) === Ordenar^2; Ordenando^(2n + 1) === Orden: D –

3

Aquí hay un patrón "de clasificación envoltorio" suggested por Michael Pilat anterior

Clear[g]; 
g[a_] := If[OrderedQ[a], a^2, Print["Failed"]]; 
g[{3, 2, 1}] 
g[a_] := g[[email protected]][[[email protected]@a]] /; Not[OrderedQ[a]]; 
g[{3, 2, 1}] 
+0

Esto me confundió al principio, creo que porque no estábamos del todo en la misma página acerca de lo que es la función g. Ver la actualización de mi respuesta. Pero, espere, supongo que lo que está haciendo aquí es obviar la necesidad de una función de ayuda por separado (lo que llamé g) al tener dos versiones de f. ¡Inteligente! Creo que esto sería menos confuso si te deshaces del g aquí. – dreeves

Cuestiones relacionadas