Parità di una permutazione


14

sfondo

La parità di una permutazione , come definita da Wikipedia , è la seguente:

Il segno o la firma di una permutazione σ è indicato con sgn (σ) e definito come +1 se σ è pari e −1 se σ è dispari.

Il segno di una permutazione può essere esplicitamente espresso come

sgn (σ) = (−1) ^ N (σ)

dove N (σ) è il numero di inversioni in σ.

In alternativa, il segno di una permutazione σ può essere definito dalla sua decomposizione nel prodotto di trasposizioni come

sgn (σ) = (−1) ^ m

dove m è il numero di trasposizioni nella decomposizione.

Per quelli di voi che non amano la zuppa di alfabeto greco in matematica, cercherò di semplificare un po 'la definizione con un esempio (anche rubato da Wikipedia).

Esempio

Si consideri la matrice di ingresso {1, 2, 3, 4, 5}, e una permutazione di esso, diciamo, {3, 4, 5, 2, 1}. Per passare dall'array originale alla sua permutazione, è necessario scambiare gli indici 0e 2, 1e 3, quindi 2e 4. Sebbene questa non sia una soluzione unica, la parità è ben definita, quindi funziona per tutti i casi.

Poiché richiede 3 swap, etichettiamo questa permutazione con una oddparità. Come ci si potrebbe aspettare, si dice che una permutazione che richiede una quantità pari di swap abbia una evenparità.

Sfida

La tua sfida è scrivere un programma nel minor numero di byte possibile per determinare la parità di una permutazione. Il tuo programma o funzione deve:

  • Accetta come argomenti due array di input (o stringhe) che rappresentano un set prima e dopo una permutazione.
  • Restituisce o stampa il carattere eper pari o odispari, data la permutazione.
  • Dovrebbe presumere che tutti gli indici nelle matrici o nelle stringhe abbiano valori univoci.

Casi test

Supponendo di aver dichiarato una funzione denominata f:

f([10], [10]) == "e"
f([10, 30, 20], [30, 20, 10]) == "e"
f([10, 30, 20, 40], [30, 20, 40, 10]) == "o"

Questo è , vince il programma più breve in byte!


4
Alla gente non piacerà il formato di output rigoroso. Che ne dici di verità per pari e falsa per dispari? (o viceversa)
CalculatorFeline

In realtà speravo di mantenere il formato di output che ho specificato a meno che qualcun altro non se ne preoccupi davvero. Modifica resisti, scenderò a compromessi.
Patrick Roberts,

@CatsAreFluffy è meglio?
Patrick Roberts,

Beh, immagino che vedremo!
Calcolatrice

Buona notte! Ecco alcuni suggerimenti per quando torni a questo (ma per favore controlla tu stesso): [10], [10] -> e(zero trasposizioni). [10 30 20], [30 20 10] -> e(due trasposizioni). [10 30 20 40], [30 20 40 10] -> o(tre trasposizioni)
Luis Mendo il

Risposte:


5

Gelatina, 13 12 byte

żṗ2</€⁺Sị“oe

Provalo online!

Come funziona

żṗ2</€⁺Sị“oe  Main link. Arguments: A, B (lists)

ż             Zip A with B. Yields an array of pairs [x, σ(x)].
 ṗ2           Generate all pairs [[x, σ(x)], [y, σ(y)]].
   </€        Reduce each pair by </€.
              This maps [[x, σ(x)], [y, σ(y)]] to [x < y, σ(x) < σ(y)].
      ⁺       Repeat the previous link, i.e., execute </€ once more.
              This maps [x < y, σ(x) < σ(y)] to ((x < y) < (σ(x) < σ(y))), which is
              true if and only if x > y and σ(x) < σ(y).
       S      Sum. This counts the number of inversions.
        ị“oe  Retrieve the letter at the corresponding index.
              Indexing is 1-based and modular, so an odd sum retrieves the first
              letter, an even sum the second.

1
È incredibilmente piccolo. Complimenti!
Patrick Roberts,

6

MATL , 17 16 byte

1 byte rimosso grazie a un suggerimento di Dennis

2$St!<Rz2\'oe'w)

Funziona con la versione corrente (15.0.0) della lingua.

Provalo online !

Spiegazione

Questo utilizza la definizione di parità in termini di inversioni. Un'inversione è una coppia di elementi nel secondo array che sono nell'ordine "sbagliato" rispetto al primo array. Poiché il primo array non deve essere ordinato, lo ordiniamo prima e lo stesso riarrangiamento necessario per quell'ordinamento viene applicato al secondo array. Quindi un'inversione corrisponde a una coppia di elementi che non aumenta nel secondo array.

Si noti inoltre che i due array di input possono essere scambiati e il risultato è lo stesso. Quindi non è importante quale array sia considerato "originale" e quale "permutato".

2$S     % implicitly take two row vectors. Sort second and apply the indices
        % of that sorting to the first
t!      % duplicate. Transpose into column vector
<       % true for elements of the column vector that exceed those of the 
        % row vector. Gives a 2D array with all pairs of comparisons
R       % keep only upper triangular part of that array
z       % number of nonzero elements. This is the number of inversions
2\      % parity of that number: gives 0 or 1
'oe'w   % push string 'eo' below the top of the stack
)       % apply index to produce 'e' or 'o'. An index 1 refers to the first
        % element, whereas 0 refers to the last. Implicitly display 

1
Questa è una soluzione davvero intelligente!
Alex A.

@AlexA. Grazie! Ho modificato la risposta per chiarire cosa fa la parte di pre-ordinamento: ordiniamo un array e quindi lo stesso riarrangiamento necessario per quell'ordinamento viene applicato all'altro array.
Luis Mendo,

1
È necessario aggiungere l'indicizzazione modulare a MATL. Ciò consentirebbe di salvare 3 byte qui.
Dennis,

@Dennis Sì, ci ho pensato spesso ... ma attualmente utilizza un formato in cui i valori negativi hanno un significato diverso. Ho scelto quello per avere indici del modulo x(1:end-2)ecc. Senza indicare esplicitamente la dimensione di x. Non sono sicuro che sia stata una buona scelta, ma credo che sia troppo tardi per cambiare ora :-) Forse troverò un modo compatibile per aggiungere l'indicizzazione modulare
Luis Mendo

... e gli indici che superano la lunghezza corrente vengono utilizzati per assegnare nuovi valori. Ma indice0 ha il significato di "ultima voce", quindi posso salvare un byte (rimuovere l'incremento). Grazie per l'idea!
Luis Mendo,

5

Ottava, 56 52 byte

Sembra che nessuno stia usando questo approccio finora: sostanzialmente sto solo usando i determinanti delle corrispondenti matrici di permutazione. L'espressione det(eye(nnz(a))(a,:))restituisce il determinante della matrice di permutazione definita dal vettore a. Quindi si tratta solo di estrarre il carattere giusto dalla stringa, a seconda del risultato.

p=@(v)eye(nnz(v))(v,:);@(a,b)'ole'(det(p(a)*p(b))+2)

2
Buona idea usare i determinanti. Ole!
Luis Mendo,

5

Haskell, 58 byte

k%l|m<-zip k l=cycle"eo"!!sum[1|(a,b)<-m,(c,d)<-m,a<c,b>d]

Uso:

*Main> [8,3,5]%[5,3,8]
'o'

Stesso metodo della mia risposta Python . haskeller orgoglioso ha salvato un byte con cycle.


1
È possibile scrivere cycle"eo"!!...invece di "eo"!!mod(...)2, salvando un byte.
orgoglioso haskeller il

4

Python 2, 68 byte

lambda*M:"eo"[sum(a<b<M>A>B for a,A in zip(*M)for b,B in zip(*M))%2]

Uso:

>>> f=lambda*M:"eo"[sum(a<b<M>A>B for a,A in zip(*M)for b,B in zip(*M))%2]
>>> f([8,3,5],[5,3,8])
'o'

Conta il numero di coppie di inversione di due elenchi zippati, i, e. valori (a,A)e (b,B)da ciascun elenco nello stesso indice con a<be A>B. Questi confronti vengono combinati come a<b<M>A>B, utilizzando la proprietà che l'elenco Mè maggiore di qualsiasi numero. La somma viene quindi presa modulo 2 e trasformata in eo o.


3

JavaScript (ES6), 73 byte

(a,b)=>"eo"[r=0,g=a=>a.map((e,i)=>a.slice(i).map(d=>r^=d<e)),g(a),g(b),r]

Poiché siamo interessati solo alla parità, qualsiasi trasposizione duplicata si annulla semplicemente. Convenientemente gli indici di array JavaScript non sono multidimensionali.


1
Posto interessante per una virgola .. non sapevo che potevi farlo. Non dimenticare di curry per -1 byte
Patrick Roberts,

2

Mathematica, 77 byte

If[Mod[Plus@@Length/@(Join[{0},#]&)/@PermutationCycles[#][[1]],2]==0,"e","o"]&

Sono d'accordo!


Comoda funzione, purtroppo nome lungo!
Patrick Roberts,

Fastidioso, vero? Odio Cycles. Aumenta le dimensioni del PermutationCyclesnome e persino PermutationCyclesè stupido, restituendo un Cyclesoggetto! `
Calcolatrice

2

Mathematica, 31 byte

If[Tr[Signature/@{##}]==0,o,e]&

Firma [elenco] fornisce la firma della permutazione necessaria per posizionare gli elementi dell'elenco in ordine canonico

Possiamo riordinare un elenco all'altro, riordinando prima un elenco in qualsiasi ordine (in questo caso l'ordine canonico) e riordinando questo elenco nell'elenco finale. Il segno della permutazione complessiva è pari, se i segni delle due sub-permutazioni sono uguali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.