2010-12-28 10 views
5

Supponiamo di avere una funzione f che prende un vettore v e restituisce un nuovo vettore con gli elementi trasformati in qualche modo. Lo fa chiamando la funzione g che presuppone che il vettore sia ordinato. Quindi voglio f da definire in questo modo:Unsort: ricordare una permutazione e annullarla

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

Qual è il modo migliore per fare il "Annulla l'ordinamento"?

Oppure potremmo ottenere veramente fantasia e hanno questo in qualche modo funziona:

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

aggiunto: Facciamo questo in calcestruzzo con un esempio di giocattolo. Supponiamo di volere una funzione f che prende un vettore e lo trasforma aggiungendo a ciascun elemento l'elemento più piccolo successivo, se presente. Questo è facile da scrivere se si assume il vettore è ordinato, quindi cerchiamo di scrivere la funzione di supporto g che rende tale ipotesi:

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

Ora, per la funzione che vogliamo davvero, f, che funziona anche se non v è ordinato :

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

risposta

2

grazie a Tomd e Yaroslav, qui è probabilmente il modo più conciso/elegante per farlo:

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

e grazie a Janus, ecco una forse più effic iente modo:

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

Si noti che lo fa 2 tipi invece di 3.

Ai posteri, ecco il mio tentativo originale, anche se non credo che abbia niente a raccomandare il sopra:

Per parlare di belisario nei commenti, il motivo per cui non sto passando g come parametro è perché sto pensando a g come funzione di supporto per f. È come se avessi una funzione f che sarebbe più facile scrivere se potessi assumere che il suo argomento fosse un vettore ordinato. Quindi scrivo la versione che lo presuppone e poi faccio questo trucco wrapper.

+1

Forse è meglio passare ** g ** come parametro. –

+1

o leggermente più efficiente, cambia l'originale in "Con [{o = Ordinamento [v]}, Parte [g [v [[o]]], Ordine [o]]]'. – Janus

6

Un metodo possibile:

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

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

Cioè,

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

inizialmente avevo appreso della summenzionata gruppo matematico, [Modificato] da un post di Andrzej Kozlowsk I

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

+1

Ordinamento^(2n) === Ordinazione^2; Ordinamento^(2n + 1) === Ordinamento: D –

3

Ecco un "ordinamento wrapper" modello suggested da Michael Pilat precedenza

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

Questo mi ha confuso all'inizio, penso perché non eravamo abbastanza sulla stessa pagina su cosa sia la funzione g. Vedi l'aggiornamento alla mia risposta. Ma, aspetta, immagino che quello che stai facendo qui stia evitando la necessità di una funzione di aiuto separata (quella che ho chiamato g) avendo due versioni di f. Inteligente! Penso che questo sarebbe meno confuso se ti sbarazzassi della g qui però. – dreeves