Classer assez bien les valeurs

23

Tâche

Étant donné une liste d'entrée d'entiers x 1 … x n , calculez une liste de rangs r 1 … r n (une permutation de {1… n} ) de sorte que x r 1  ≤ x r 2  ≤… ≤ x r n . Ensuite, pour chaque x i , remplacez son rang par la moyenne arithmétique des rangs de toutes les valeurs de x qui sont égales à x i . (Autrement dit, chaque fois qu'il existe un lien entre des valeurs égales dans x , redistribuez équitablement les rangs parmi tous.) Sortez la liste modifiée des rangs r ' n 1 … r' .

(Pour les geeks de statistiques: un tel classement des observations est utilisé dans le test de Mann-Whitney U (méthode deux, étape 1.))

Exemple

Étant donné une liste d'entrée [3, -6, 3, 3, 14, 3] , la première liste de rangs serait [2, 1, 3, 4, 6, 5] , qui trierait la liste en [-6, 3, 3, 3, 3, 14] . Ensuite, les rangs des 3 s de la liste d'entrée sont égalisés en (2 + 3 + 4 + 5) ÷ 4 = 3,5 . La sortie finale est [3,5, 1, 3,5, 3,5, 6, 3,5] .

Cas de test

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

Règles

Il s'agit de , donc le code le plus court en octets l'emporte.

Lynn
la source

Réponses:

7

Gelée , 10 8 octets

ð_'Ṡ‘S‘H

Enregistré 2 octets en utilisant l' cmpastuce de la réponse de @ xnor .

Essayez-le en ligne! ou vérifiez tous les cas de test .

Comment ça marche

ð_'Ṡ‘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
la source
6

Pyth, 12

m+l<#dQ.OS/Q

Suite de tests

Pour chaque valeur, cela calcule la moyenne arithmétique de [1..frequency]et ajoute le nombre de valeurs inférieures à la valeur actuelle.

Cela fonctionne car pour chaque valeur, nous calculerions:

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

que nous pouvons simplifier pour:

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

et encore:

(frequency + 1) / 2 + count_less

Cependant, en Pyth, il était golfeur de calculer le premier summand en utilisant la moyenne intégrée, plutôt que cette autre formule.

FryAmTheEggman
la source
4

Python 2, 51 octets

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

Pour chaque élément y, l' cmpexpression donne 2 points pour chaque plus petit xet 1 point pour chaque égal x. Cette somme est redimensionnée dans la bonne plage en ajoutant 1 et en divisant par deux. Le 2.est nécessaire pour éviter la division entière.

Python 3, 52 octets

Python 3 manque cmp, nécessitant une expression booléenne (+2 octets), mais il a une division flottante (-1 octet).

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

MATL , 14 octets

7#utG&S&S2XQw)

Essayez-le en ligne! Ou vérifiez tous les cas de test (version légèrement modifiée du code; chaque résultat est sur une ligne différente).

      % 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
la source
3

R, 17 12 octets

Prend l'entrée des sorties STDIN vers STDOUT. Si la sortie est flexible, nous pouvons abandonner le cat().

rank(scan())

Assez simple, utilise le rang intégré par défaut à la moyenne pour un bris d'égalité.

Utilisé:

> 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
la source
Vous pouvez laisser tomber le cat(), si cela ne dépend que de moi. Je ne sais pas quel est le consensus communautaire, cependant.
Lynn
@Lynn Merci je le ferai. Je peux toujours le remettre.
MickyT
2

J, 18 octets

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

Basé sur la solution de Dennis utilisant xnor méthode .

L'utilisation d'une approche directe nécessite 24 octets pour moi.

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

Usage

   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
miles
la source
1

En fait, 18 octets

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

Essayez-le en ligne!

Il s'agit essentiellement d'un portage de la solution Python de xnor .

Explication:

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

APL, 17 caractères

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

En supposant que la liste est stockée dans X.

Explication:

Notez que APL évalue les expressions de droite à gauche. Ensuite:

  • ∘.=⍨X= X∘.=X∘.=est le produit extérieur utilisant =comme fonction dyadique. (Où vous vous multiplieriez normalement. Le produit mathématique externe peut donc s'écrire ∘.×.)
  • La matrice résultante est stockée dans yet yest directement pliée en utilisant +pour donner un vecteur du nombre d'objets égaux pour chaque rang (appelons-le z←+/y).
  • ⍋X renvoie les rangs de X
  • y+.×⍋X donne le produit intérieur de notre matrice y avec ce vecteur.
  • Le résultat est divisé (par composant) par z.
user2070206
la source
0

Julia, 30 octets

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

Cela utilise une approche de la réponse de @ xnor . Julia acmp , mais il ne vectorise pas.

Essayez-le en ligne!

Dennis
la source
0

JavaScript (ES6), 49 48 octets

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

Edit: enregistré 1 octet en reformulant l'expression afin qu'elle ressemble maintenant à la réponse Python 3 de @ xnor.

Neil
la source