Dado um vetor dimensional com entradas reais, encontre uma permutação mais próxima de (1,2, ..., n) com relação à distância l_1 .
Detalhes
- Se for mais conveniente, você pode usar permutações de . Se houver várias permutações mais próximas, você poderá produzir qualquer uma ou, alternativamente, todas elas.
- A distância entre dois vetores é definida como
- Se desejar, você pode assumir que a entrada consiste apenas em números inteiros.
Exemplos
[0.5 1] -> [1 2], [2 1]
c*[1 1 ... 1] -> any permutation
[1 4 2 6 2] -> [1 4 3 5 2], [1 4 2 5 3]
[1 3 5 4 1] -> [2 3 5 4 1], [1 3 5 4 2]
[7 7 3 2 5 6 4 2] -> [8 7 3 2 5 6 4 1], [8 7 3 1 5 6 4 2], [7 8 3 2 5 6 4 1], [7 8 3 1 5 6 4 2]
[-2 4 5 7 -1 9 3] -> [1 4 5 6 2 7 3], [2 4 5 6 1 7 3], [1 4 5 7 2 6 3], [2 4 5 7 1 6 3]
[0 4 2 10 -1 10 5] -> [1 4 2 6 3 7 5], [1 4 3 6 2 7 5], [2 4 3 6 1 7 5], [3 4 2 6 1 7 5], [1 4 2 7 3 6 5], [1 4 3 7 2 6 5], [2 4 3 7 1 6 5], [3 4 2 7 1 6 5]
Script de oitava para gerar mais exemplos.
v
serão maiores que0
? Ou pelo menos não0
?v
podem ser inteiros. (Adicionado mais alguns exemplos.)[1.6 2]
é um caso de teste importante (algoritmo ganancioso / classificação lexicográfica dá a resposta errada).Respostas:
Python 2 , 60 bytes
Experimente online!
Usa indexação zero.
Um algoritmo rápido com uma ideia simples. Se em vez precisam permutar a lista de entrada para torná-lo tão perto de(1,2,...,n) que possível, devemos apenas uma espécie, como comprovado abaixo. Desde que nós estamos permutando vez ( 1 , 2 , . . . , N ) , nós escolhemos a permutação daquele ordenado da mesma forma que a lista de entrada, como no meu desafio Imitar uma ordenação (exceto a entrada pode ter repete). (Edit: miles apontou esse desafio mais idêntico , onde Dennis tem a mesma resposta .)
Note-se que a única propriedade de( 1 , 2 , . . . , N ) que usamos é que ele é classificado, de modo que o mesmo algoritmo iria trabalhar para permutar qualquer lista dada para minimizar o seu raio de qualquer lista fixa.
No código, o único objetivo de
z=zip(l,range(len(l)))
é diferenciar os elementos de entrada, ou seja, evitar vínculos, mantendo as mesmas comparações entre elementos desiguais. Se a entrada que garantimos não tiver repetições, poderíamos removê-la e apenas terlambda l:map(sorted(l).index,l)
.fonte
05AB1E , 7 bytes
Experimente online!
Explicação
fonte
Perl 6 , 44 bytes
Experimente online!
Codeblock anônimo que retorna a primeira permutação mínima com indexação 0.
Explicação:
Eu acho que também posso me livrar
.sum
e classificar apenas pela lista de valores absolutos, mas não tenho certeza se isso é realmente correto, apesar de passar nos meus casos de teste atuais.fonte
[0.6 1]
(supondo que estejamos indexados a 0), onde, se você otimizar para o primeiro valor, obtém[1,0]
uma pontuação de 1,4, mas se otimizar para todo o vetor, o 1 é mais valioso na segunda posição para uma pontuação. de 0,6.Geléia , 8 bytes
Experimente online!
fonte
Geléia , 5 bytes
Um link monádico que aceita uma lista de números que produz uma lista de números inteiros.
Experimente online! Ou veja a suíte de testes .
Quão?
NB
L
(comprimento de) funcionaria no lugar doJ
dadoœ?
dado um número inteiro;,n
à direita, implicitamente aumentaria o intervalo[1..n]
para trabalhar, masJ
é explícito.fonte
Ruby ,
6360 bytesExperimente online!
Há um truque de matemática aqui que também pode ser útil em outras respostas - em vez de minimizar a soma dos valores absolutos das diferenças, maximizamos a soma dos produtos. Por que isso funciona?
Minimizar a soma de
(x-y) squared
não é equivalente a minimizar a soma de|x-y|
, mas sempre dará uma resposta válida, apenas prioriza a redução de grandes diferenças em relação às pequenas, enquanto o desafio real é indiferente entre as duas.Mas
(x-y)*(x-y)
=x*x+y*y-2*x*y
. Como os termos quadrados sempre aparecem em algum lugar da soma de qualquer permutação, eles não afetam o resultado, para que possamos simplificá-lo-2*x*y
. Os2
fatores fora, para que possamos simplificar-x*y
. Então, se mudarmos de minimizado para maximizado, podemos simplificar parax*y
.Intuitivamente, isso é semelhante à observação de que, se você estiver tentando maximizar a metragem quadrada usando um conjunto de paredes horizontais e verticais, é melhor emparelhar paredes com tamanho aproximado umas das outras para criar salas que sejam o mais próximo possível da praça.
3*3 + 4*4 = 25
enquanto3*4 + 4*3 = 24
.Editar: salvou três bytes gerando e avaliando uma sequência de formato em vez de usar zip e soma.
fonte
Gaia , 13 bytes
Experimente online!
fonte
JavaScript (ES6), 61 bytes
Baseado no insight do xnor .
Experimente online!
Comentado
JavaScript (ES6),
130128 bytesNão
deve serdefinitivamente é uma forma mais direta ...Indexado a 0.
Experimente online! (com saída indexada 1)
Quão?
A função auxiliarg calcula todas as permutações de ( 0 , . . . , N - 1 ) , Onde n é o comprimento implícito da matriz de entrada a [] .
Para cada permutaçãop , calculamos:
Eventualmente, retornamos a permutação que leva ao menork .
fonte
Wolfram Language (Mathematica) , 14 bytes
Experimente online!
Baseado no insight do xnor .
fonte
Python 2 ,
149126112 bytes-23 bytes graças a Mr. Xcoder
-14 bytes graças ao xnor
Experimente online!
Usa permutações de (0 ... n-1).
fonte
functools
mais.reduce
geralmente é um exagero, especialmente aqui onde você está adicionando coisas. Eu acho que você pode fazersum(abs(p-q)for p,q in zip(x,a))
.sem qualquer pacote de permutação
Python 3 , 238 bytes
Experimente online!
fonte
Wolfram Language (Mathematica) , 57 bytes
Experimente online!
fonte
Japonês
-g
, 12 bytesTente
Para indexado 0, substitua os 2 primeiros bytes por
m,
para mapear a matriz para seus índices.fonte
J ,
25bytes 8Experimente online!
Uma resposta muito mais curta, com base na brilhante ideia do xnor.
resposta original
J , 25 bytes
Experimente online!
fonte