Paridade de uma permutação

14

fundo

A paridade de uma permutação , conforme definida pela wikipedia , é a seguinte:

O sinal ou assinatura de uma permutação σ é denotado sgn (σ) e definido como +1 se σ for par e -1 se σ for ímpar.

O sinal de uma permutação pode ser expresso explicitamente como

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

onde N (σ) é o número de inversões em σ.

Alternativamente, o sinal de uma permutação σ pode ser definido a partir de sua decomposição no produto das transposições como

sgn (σ) = (−1) ^ m

onde m é o número de transposições na decomposição.

Para aqueles que não gostam da sopa do alfabeto grego em suas contas, tentarei simplificar um pouco a definição com um exemplo (também roubado da wikipedia).

Exemplo

Considere a matriz de entrada {1, 2, 3, 4, 5}e uma permutação dela, digamos {3, 4, 5, 2, 1},. Para passar da matriz original para sua permutação, você deve trocar índices 0e 2, 1e 3, then 2e 4. Embora essa não seja uma solução exclusiva, a paridade é bem definida e, portanto, funciona para todos os casos.

Como requer 3 swaps, rotulamos essa permutação com oddparidade. Como você poderia esperar, uma permutação que requer uma quantidade uniforme de swaps é considerada evenparidade.

Desafio

Seu desafio é escrever um programa no menor número de bytes possível para determinar a paridade de uma permutação. Seu programa ou função deve:

  • Aceite como argumentos, duas matrizes de entrada (ou cadeias) representando um conjunto antes e depois de uma permutação.
  • Retorne ou imprima o caractere epara par ou oímpar, dada a permutação.
  • Deve assumir que todos os índices nas matrizes ou cadeias tenham valores exclusivos.

Casos de teste

Supondo que você declarou uma função denominada f:

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

Este é o , o programa mais curto em bytes vence!

Patrick Roberts
fonte
4
As pessoas não vão gostar do formato de saída estrito. Que tal verdade para par e falsidade para ímpar? (ou
CalculatorFeline
Na verdade, eu esperava manter o formato de saída especificado, a menos que alguém realmente se incomodasse com isso. Editar espera, eu vou comprometer.
Patrick Roberts
@CatsAreFluffy é melhor assim?
22416 Patrick Roberts
Bem, acho que vamos ver!
CalculatorFeline
Boa noite! Aqui estão algumas sugestões para quando você voltar a isso (mas verifique por si mesmo): [10], [10] -> e(zero transposição). [10 30 20], [30 20 10] -> e(duas transposições). [10 30 20 40], [30 20 40 10] -> o(três transposições)
Luis Mendo

Respostas:

5

Gelatina, 13 12 bytes

żṗ2</€⁺Sị“oe

Experimente online!

Como funciona

żṗ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.
Dennis
fonte
1
Isso é impressionantemente pequeno. Parabéns!
22416 Patrick Roberts
6

MATL , 17 16 bytes

1 byte removido graças a uma sugestão de Dennis

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

Isso funciona na versão atual (15.0.0) do idioma.

Experimente online !

Explicação

Isso usa a definição de paridade em termos de inversões. Uma inversão é um par de elementos na segunda matriz que estão na ordem "incorreta" em comparação com a primeira matriz. Como a primeira matriz não precisa ser classificada, primeiro a classificamos e o mesmo rearranjo necessário para essa classificação é aplicado à segunda matriz. Então uma inversão corresponde a um par de elementos que não está aumentando na segunda matriz.

Observe também que as duas matrizes de entrada podem ser trocadas e o resultado é o mesmo. Portanto, não é importante qual array é considerado o "original" e qual o "permutado".

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 
Luis Mendo
fonte
1
Esta é uma solução realmente inteligente!
Alex A.
@AlexA. Obrigado! Editei a resposta para esclarecer o que a peça de pré-encomenda faz: classificamos uma matriz e, em seguida, o mesmo rearranjo necessário para essa classificação é aplicado à outra matriz.
Luis Mendo
1
Você deve adicionar a indexação modular ao MATL. Isso economizaria 3 bytes aqui.
Dennis
@ Dennis Sim, eu sempre pensei nisso ... mas atualmente ele usa um formato em que valores negativos têm um significado diferente. Eu escolhi isso para ter índices do formulário x(1:end-2)etc, sem indicar explicitamente o tamanho de x. Não tenho certeza se foi uma boa escolha, mas eu acho que é tarde demais para mudar agora :-) Talvez eu vou encontrar uma maneira compatível para adicionar indexação modular
Luis Mendo
... e índices que excedem o comprimento atual são usados ​​para atribuir novos valores. Mas índice 0tem o significado de "última entrada", para que eu possa salvar um byte (remover o incremento). Obrigado pela ideia!
Luis Mendo
5

Oitava, 56 52 bytes

Parece que ninguém está usando essa abordagem até agora: Basicamente, estou apenas usando os determinantes das matrizes de permutação correspondentes. A expressão det(eye(nnz(a))(a,:))retorna o determinante da matriz de permutação definida pelo vetor a. Depois, basta extrair o caractere certo da string, dependendo do resultado.

p=@(v)eye(nnz(v))(v,:);@(a,b)'ole'(det(p(a)*p(b))+2)
flawr
fonte
2
Boa idéia para usar os determinantes. Ole!
Luis Mendo
5

Haskell, 58 bytes

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'

O mesmo método da minha resposta em Python . proud haskeller salvou um byte com cycle.

xnor
fonte
1
Você pode escrever cycle"eo"!!...Em vez de "eo"!!mod(...)2salvar um byte.
23416163Preço:
4

Python 2, 68 bytes

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 o número de pares de inversão de duas listas compactadas, i, e. valores (a,A)e (b,B)de cada lista no mesmo índice com a<be A>B. Essas comparações são combinadas como a<b<M>A>B, usando a propriedade que a lista Mé maior que qualquer número. A soma é então tomada no módulo 2 e transformada em eou o.

xnor
fonte
3

JavaScript (ES6), 73 bytes

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

Como estamos interessados ​​apenas na paridade, qualquer transposição duplicada simplesmente é cancelada. Convenientemente, os subscritos da matriz do JavaScript não são multidimensionais.

Neil
fonte
1
Lugar interessante para uma vírgula .. não sabia que você poderia fazer isso. Não se esqueça sobre currying para -1 byte
Patrick Roberts
2

Mathematica, 77 bytes

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

Concordo!

CalculatorFeline
fonte
Função útil, infelizmente, nome longo!
Patrick Roberts
Irritante, certo? Eu odeio Cycles. Ele aumenta o tamanho do PermutationCyclesnome e até PermutationCyclesé estúpido, retornando um Cyclesobjeto! ``
CalculatorFeline
2

Mathematica, 31 bytes

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

Assinatura [lista] fornece a assinatura da permutação necessária para colocar os elementos da lista em ordem canônica

Podemos reordenar uma lista para a outra, primeiro reordenando uma lista para qualquer ordem (neste caso, a ordem canônica) e reordenando essa lista para a lista final. O sinal da permutação geral é uniforme, se os sinais das duas sub-permutações forem iguais.

Murphy
fonte