Значения справедливого ранга

23

задача

Для заданного входного списка целых чисел x 1 … x n вычислить список рангов r 1 … r n (перестановка {1… n} ) так, чтобы x r 1  ≤ x r 2  ≤… ≤ x r n . Затем для каждого x i замените его ранг средним арифметическим рангов всех значений в x , равных x i . (То есть, когда есть связь между равными значениями в x , достаточно перераспределить ранги между всеми ними.) Выведите измененный список рангов r ' 1 … r'п .

(Для фанатов статистики: такое ранжирование наблюдений используется в U- тесте Манна – Уитни (метод 2, шаг 1.))

пример

Учитывая входной список [3, -6, 3, 3, 14, 3] , первым списком рангов будет [2, 1, 3, 4, 6, 5] , который будет сортировать список в [-6, 3, 3, 3, 3, 14] . Затем ранги всех 3 с в списке входов распределяются по (2 + 3 + 4 + 5) ÷ 4 = 3,5 . Окончательный результат составляет [3,5, 1, 3,5, 3,5, 6, 3,5] .

Контрольные примеры

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

правила

Это , поэтому выигрывает самый короткий код в байтах.

Линн
источник

Ответы:

7

Желе , 10 8 байт

ð_'Ṡ‘S‘H

Сохранено 2 байта с помощью cmpтрюка из ответа @ xnor .

Попробуйте онлайн! или проверьте все контрольные примеры .

Как это работает

ð_'Ṡ‘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.
Деннис
источник
6

Пиф, 12

m+l<#dQ.OS/Q

Тестирование

Для каждого значения это вычисляет среднее арифметическое [1..frequency]и добавляет количество значений меньше текущего.

Это работает, потому что для каждого значения мы вычисляем:

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

который мы можем упростить до:

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

и снова:

(frequency + 1) / 2 + count_less

Тем не менее, в Pyth было сложнее вычислить первое слагаемое, используя среднее значение, а не эту другую формулу.

FryAmTheEggman
источник
4

Python 2, 51 байт

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

Для каждого элемента y, то cmpвыражение дает 2 очка за каждый меньше , xи 1 балл за каждый равен x. Эта сумма пересчитывается в правильный диапазон путем добавления 1 и деления пополам. Это 2.необходимо, чтобы избежать целочисленного деления.

Python 3, 52 байта

В Python 3 отсутствуют cmpбулевы выражения (+2 байта), но есть деление с плавающей запятой (-1 байт).

lambda l:[-~sum((y>x)+(y>=x)for x in l)/2for y in l]
XNOR
источник
3

MATL , 14 байтов

7#utG&S&S2XQw)

Попробуйте онлайн! Или проверьте все контрольные примеры (слегка измененная версия кода; каждый результат находится в отдельной строке).

      % 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 байт

Принимает вход от выходов STDIN к STDOUT. Если вывод является гибким, то мы можем отказаться cat().

rank(scan())

Довольно просто, использует встроенный ранг, который по умолчанию усредняется для тай-брейка.

В использовании:

> 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
источник
Вы можете бросить cat(), если это до меня. Я не знаю, что такое консенсус сообщества.
Линн
@ Линн Спасибо, я сделаю. Я всегда могу положить это обратно.
MickyT
2

J, 18 байт

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

На основе решения Денниса с использованием метода xnor .

Использование прямого подхода требует от меня 24 байта .

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

использование

   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

На самом деле, 18 байт

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

Попробуйте онлайн!

По сути это порт решения xnor Python .

Объяснение:

;╗`╝╜"╛-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
источник
1

APL, 17 символов

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

Предполагая, что список хранится в X.

Объяснение:

Обратите внимание, что APL оценивает выражения справа налево. Затем:

  • ∘.=⍨X= X∘.=Xгде ∘.=это внешнее произведение, используемое в =качестве двоичной функции. (Там, где вы обычно умножаете. Таким образом, математический внешний продукт может быть записан как ∘.×.)
  • Результирующая матрица сохраняется yи yскладывается напрямую, используя +для определения вектора количество равных объектов для каждого ранга (давайте назовем его z←+/y).
  • ⍋X возвращает в ряды X
  • y+.×⍋X дает внутреннее произведение нашей матрицы у с этим вектором.
  • Результат делится (по компонентам) на z.
user2070206
источник
0

JavaScript (ES6), 49 48 байт

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

Редактировать: 1 байт сохранен путем переформулировки выражения, чтобы оно теперь выглядело как ответ @ xnor's Python 3.

Нил
источник