Valores razoáveis

23

Tarefa

Dada uma lista de entrada de números inteiros x 1 … x n , calcule uma lista de classificações r 1 … r n (uma permutação de {1… n} ) para que x r 1  ≤ x r 2  ≤… ≤ x r n . Então, para cada x i , substitua sua classificação pela média aritmética das classificações de todos os valores em x iguais a x i . (Ou seja, sempre que houver um empate entre valores iguais em x , redistribua razoavelmente as classificações entre todas elas.) Crie a lista modificada de classificações r ' 1 … r'n .

(Para geeks de estatística: esse ranking de observações é usado no teste U de Mann – Whitney (método dois, etapa 1.))

Exemplo

Dada uma lista de entrada [3, -6, 3, 3, 14, 3] , a primeira lista de classificações seria [2, 1, 3, 4, 6, 5] , que classificaria a lista em [-6, 3, 3, 3, 3, 14] . Então, as classificações para todos os 3 s na lista de entrada são niveladas em (2 + 3 + 4 + 5) ÷ 4 = 3,5 . A saída final é [3.5, 1, 3.5, 3.5, 6, 3.5] .

Casos de teste

[4, 1, 4] -> [2.5, 1.0, 2.5]
[5, 14, 14, 14, 14, 5, 14] -> [1.5, 5.0, 5.0, 5.0, 5.0, 1.5, 5.0]
[9, 9, -5, -5, 13, -5, 13, 9, 9, 13] -> [5.5, 5.5, 2.0, 2.0, 9.0, 2.0, 9.0, 5.5, 5.5, 9.0]
[13, 16, 2, -5, -5, -5, 13, 16, -5, -5] -> [7.5, 9.5, 6.0, 3.0, 3.0, 3.0, 7.5, 9.5, 3.0, 3.0]

Regras

Isso é , então o código mais curto em bytes vence.

Lynn
fonte

Respostas:

7

Geléia , 10 8 bytes

ð_'Ṡ‘S‘H

Economizou 2 bytes usando o cmptruque da resposta de @ xnor .

Experimente online! ou verifique todos os casos de teste .

Como funciona

ð_'Ṡ‘S‘H  Main link. Left argument: A (list of values)

ð         Make the chain dyadic, setting the right argument to A.
 _'       Spawned subtraction; compute the matrix of differences.
   Ṡ      Apply the sign function to each difference.
    ‘     Increment.
     S    Sum across columns.
      ‘   Increment.
       H  Halve.
Dennis
fonte
6

Pyth, 12

m+l<#dQ.OS/Q

Suíte de teste

Para cada valor, calcula a média aritmética de [1..frequency]e adiciona a contagem de valores menor que o atual.

Isso funciona porque, para cada valor, calcularíamos:

(1 / frequency) * sum (i = 1..frequency) i + count_less

que podemos simplificar para:

(1 / frequency) * [ frequency * (frequency + 1) / 2 + count_less * frequency ]

e novamente para:

(frequency + 1) / 2 + count_less

No entanto, em Pyth, era mais golfista calcular a primeira demanda usando a média incorporada, em vez dessa outra fórmula.

FryAmTheEggman
fonte
4

Python 2, 51 bytes

lambda l:[-~sum(1+cmp(y,x)for x in l)/2.for y in l]

Para cada elemento y, a cmpexpressão fornece 2 pontos para cada menor xe 1 ponto para cada igual x. Essa soma é redimensionada para o intervalo correto adicionando 1 e diminuindo pela metade. O 2.é necessário para evitar a divisão inteira.

Python 3, 52 bytes

O Python 3 não possui cmp, exigindo uma expressão booleana (+2 bytes), mas possui divisão flutuante (-1 byte).

lambda l:[-~sum((y>x)+(y>=x)for x in l)/2for y in l]
xnor
fonte
3

MATL , 14 bytes

7#utG&S&S2XQw)

Experimente online! Ou verifique todos os casos de teste (versão ligeiramente modificada do código; cada resultado está em uma linha diferente).

      % Implicit input. Example: [5 14 14 14 14 5 14]
7#u   % Replace each value by a unique, integer label. Example: [1; 2; 2; 2; 2; 1; 2]
t     % Duplicate
G&S   % Push input again. Sort and get indices of the sorting. Example: [1 6 2 3 4 5 7]
&S    % Sort and get the indices, again. This gives the ranks. Example: [1 3 4 5 6 2 7]
2XQ   % Compute mean of ranks for equal values of the integer label. Example: [1.5; 5]
w     % Swap top two elements in stack
)     % Index the means with the integer labels. Example: [1.5; 5; 5; 5; 5; 1.5; 5]
      % Implicit display
Luis Mendo
fonte
3

R, 17 12 bytes

Leva a entrada das saídas STDIN para STDOUT. Se a saída é flexível, podemos abandonar o cat().

rank(scan())

Bastante simples, usa a classificação interna que tem como padrão a média para um desempate.

Em uso:

> rank(scan())
1: 5 14 14 14 14 5 14
8: 
Read 7 items
[1] 1.5 5.0 5.0 5.0 5.0 1.5 5.0
> rank(scan())
1: 3 -6 3 3 14 3
7: 
Read 6 items
[1] 3.5 1.0 3.5 3.5 6.0 3.5
> 
MickyT
fonte
Você pode largar o cat(), se depender de mim. Mas não sei qual é o consenso da comunidade.
Lynn
@ Lynn Obrigado eu vou. Eu sempre posso colocá-lo de volta.
MickyT
2

J, 18 bytes

1-:@+1+/"1@:+*@-/~

Baseado na solução de Dennis usando o método xnor .

Usar uma abordagem direta requer 24 bytes para mim.

(i.~~.){](+/%#)/.1+/:@/:

Uso

   f =: 1-:@+1+/"1@:+*@-/~
   f 3 _6 3 3 14 3
3.5 1 3.5 3.5 6 3.5
   f 4 1 4
2.5 1 2.5
   f 5 14 14 14 14 5 14
1.5 5 5 5 5 1.5 5
   f 9 9 _5 _5 13 _5 13 9 9 13
5.5 5.5 2 2 9 2 9 5.5 5.5 9
   f 13 16 2 _5 _5 _5 13 16 _5 _5
7.5 9.5 6 3 3 3 7.5 9.5 3 3
milhas
fonte
1

Na verdade, 18 bytes

;╗`╝╜"╛-su"£MΣu½`M

Experimente online!

Essa é essencialmente uma porta da solução Python do xnor .

Explicação:

;╗`╝╜"╛-su"£MΣu½`M
;╗                  push a copy of input to reg0
  `             `M  for x in input:
   ╝                  push x to reg1
    ╜                 push input from reg0
     "    "£M         for y in input:
      ╛                 push x from reg0
       -s               cmp(y,x) (sgn(y-x))
         u              add 1
             Σu½      sum, add 1, half
Mego
fonte
1

APL, 17 caracteres

(y+.×⍋X)÷+/y←∘.=⍨X

Supondo que a lista esteja armazenada X.

Explicação:

Observe que o APL avalia expressões da direita para a esquerda. Então:

  • ∘.=⍨X= X∘.=Xonde ∘.=está o produto externo usando =como função diádica. (Onde você normalmente se multiplicaria. Portanto, o produto externo matemático pode ser escrito como ∘.×.)
  • A matriz resultante é armazenada ye yé dobrada diretamente usando +para fornecer um vetor do número de objetos iguais para cada classificação (vamos chamá-lo z←+/y).
  • ⍋X retorna as fileiras de X
  • y+.×⍋X fornece o produto interno de nossa matriz y com esse vetor.
  • O resultado é dividido (componente) por z.
user2070206
fonte
0

Julia, 30 bytes

!x=-~sum((x.>x')+(x.>=x'),2)/2

Isso usa uma abordagem da resposta do @ xnor . Julia tem cmp, mas não se vetoriza.

Experimente online!

Dennis
fonte
0

JavaScript (ES6), 49 48 bytes

a=>a.map(n=>a.reduce((r,m)=>r+(n>m)+(n>=m),1)/2)

Edit: Salvo 1 byte, reformulando a expressão para que agora pareça com a resposta Python 3 do @ xnor.

Neil
fonte