Valores bastante justos


23

Tarea

Dada una lista de entrada de enteros x 1 ... x n , calcule una lista de rangos r 1 ... r n (una permutación de {1 ... n} ) para que x r 1  ≤ x r 2  ≤ ... ≤ x r n . Luego, para cada x i , reemplace su rango por la media aritmética de los rangos de todos los valores en x que sean iguales a x i . (Es decir, siempre que haya un vínculo entre los valores iguales en x , redistribuya bastante bien los rangos entre todos ellos). Genere la lista modificada de rangos r ' 1 ... r'n .

(Para geeks estadísticos: tal clasificación de observaciones se usa en la prueba U de Mann – Whitney (método dos, paso 1.))

Ejemplo

Dada una lista de entrada [3, -6, 3, 3, 14, 3] , la primera lista de rangos sería [2, 1, 3, 4, 6, 5] , que ordenaría la lista en [-6, 3, 3, 3, 3, 14] . Luego, los rangos de los 3 s en la lista de entrada se igualan en (2 + 3 + 4 + 5) ÷ 4 = 3.5 . El resultado final es [3.5, 1, 3.5, 3.5, 6, 3.5] .

Casos de prueba

[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]

Reglas

Este es el , por lo que gana el código más corto en bytes.


Respuestas:



6

Pyth, 12

m+l<#dQ.OS/Q

Banco de pruebas

Para cada valor, esto calcula la media aritmética de [1..frequency]y agrega el recuento de valores menores que el actual.

Esto funciona porque para cada valor calcularíamos:

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

que podemos simplificar a:

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

y nuevamente a:

(frequency + 1) / 2 + count_less

Sin embargo, en Pyth era más golfoso calcular el primer sumando usando la media incorporada, en lugar de esta otra fórmula.


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, la cmpexpresión da 2 puntos por cada más pequeño xy 1 punto por cada igual x. Esta suma se reescala en el rango correcto agregando 1 y reduciendo a la mitad. Se 2.necesita para evitar la división de enteros.

Python 3, 52 bytes

Python 3 carece cmp, lo que requiere una expresión booleana (+2 bytes), pero tiene división flotante (-1 byte).

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

3

MATL , 14 bytes

7#utG&S&S2XQw)

Pruébalo en línea! O verifique todos los casos de prueba (versión ligeramente modificada del código; cada resultado está en una línea 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


3

R, 17 12 bytes

Toma la entrada de las salidas STDIN a STDOUT. Si la salida es flexible, podemos deshacernos del cat().

rank(scan())

Bastante simple, usa el rango incorporado que por defecto es el promedio para un desempate.

En 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
> 

Puede soltar el cat(), si depende de mí. Sin embargo, no sé cuál es el consenso de la comunidad.
Lynn

@ Lynn Gracias lo haré. Siempre puedo devolverlo.
MickyT

2

J, 18 bytes

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

Basado en la solución de Dennis usando el método de xnor .

Usar un enfoque directo requiere 24 bytes para mí.

(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

1

En realidad, 18 bytes

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

Pruébalo en línea!

Esto es esencialmente un puerto de la solución Python de xnor .

Explicación:

;╗`╝╜"╛-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

1

APL, 17 caracteres

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

Suponiendo que la lista esté almacenada en X.

Explicación:

Tenga en cuenta que APL evalúa las expresiones de derecha a izquierda. Luego:

  • ∘.=⍨X= X∘.=Xdonde ∘.=se usa el producto externo =como función diádica. (Donde normalmente se multiplicaría. Por lo tanto, el producto externo matemático puede escribirse como ∘.×).
  • La matriz resultante se almacena yy yse pliega directamente usando +para dar un vector del número de objetos iguales para cada rango (llamémoslo z←+/y).
  • ⍋X devuelve las filas de X
  • y+.×⍋X da el producto interno de nuestra matriz y con este vector.
  • El resultado se divide (componente sabio) por z.


0

JavaScript (ES6), 49 48 bytes

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

Editar: se guardó 1 byte reformulando la expresión para que ahora se vea como la respuesta Python 3 de @ xnor.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.