Показать пять лучших комментариев на пост SE

30

Скрипт Stack Exchange определяет, какие пять комментариев к вопросам или ответам изначально видны на главной странице сайтов по количеству голосов на них; отображаются пять комментариев с наибольшим количеством голосов. Ваша задача - воссоздать это поведение.

Напишите полную программу или функцию, принимающую ввод через STDIN, аргументы командной строки или аргументы функции, и печатает или возвращает первые пять оценок комментариев. Входные данные будут массивом целых чисел, представляющих количество голосов в комментариях к некоторому сообщению. Например, ввод

0, 2, 5, 4, 0, 1, 0

означает, что у первого комментария нет голосов, у второго - два, у третьего - пять, у четвертого - четыре и т. д. Порядок оценок комментариев должен оставаться неизменным в выходных данных.

Если входные данные содержат пять или меньше оценок комментариев, то выходные данные не должны содержать ничего, кроме указанных. Если два или более баллов за комментарий одинаковы, должны отображаться первые баллы. Вы можете предположить, что входной массив будет содержать как минимум один комментарий.

Числа в выходных данных должны быть легко различимы (поэтому 02541 для случая 1 недопустимо). В противном случае нет никаких ограничений на выходной формат; числа могут быть разделены пробелом или новой строкой, или они могут быть в формате списка и т. д.

Тестовые случаи:

[0, 2, 5, 4, 0, 1, 0] -> [0, 2, 5, 4, 1]
[2, 1, 1, 5, 3, 6] -> [2, 1, 5, 3, 6]
[0, 4, 5] -> [0, 4, 5]
[1, 1, 5, 1, 1, 5] -> [1, 1, 5, 1, 5]
[0, 2, 0, 0, 0, 0, 0, 0] -> [0, 2, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0] -> [0, 0, 0, 0, 1]
[5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7] -> [5, 8, 7, 6, 7]
[6, 3, 2, 0, 69, 22, 0, 37, 0, 2, 1, 0, 0, 0, 5, 0, 1, 2, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2] -> [6, 69, 22, 37, 5]

Последний пример был взят из этого вопроса переполнения стека .

Если возможно, укажите в своем сообщении ссылку, по которой ваша заявка может быть размещена в Интернете.

Это код гольф, поэтому выигрывает самый короткий код в байтах. Удачи!

тротил
источник
Должны ли мы сохранить порядок?
Конор О'Брайен
@ CᴏɴᴏʀO'Bʀɪᴇɴ Да. Порядок появления целых чисел не должен меняться.
TNT

Ответы:

10

Желе , 6 байт

NỤḣ5Ṣị

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

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

NỤḣ5Ṣị    Main link. Input: A (list)

N         Negate (multiply by -1) all elements of A.
 Ụ        Grade the result up.
          This consists in sorting the indices of A by their negated values.
          The first n indices will correspond to the n highest vote counts,
          tie-broken by order of appearance.
  ḣ5      Discard all but the first five items.
    Ṣ     Sort those indices.
          This is to preserve the comments' natural order.
     ị    Retrieve the elements of A at those indices.
Деннис
источник
10

Python 2, 58 байт

x=input()[::-1]
while x[5:]:x.remove(min(x))
print x[::-1]

Проверьте это на Ideone .

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

list.removeудаляет первое вхождение, если его аргумент из указанного списка. Обращая список x , мы, по сути, достигаем того, что он удаляет последнее вхождение вместо этого.

Таким образом, достаточно продолжать удалять комментарий с минимальным количеством голосов, пока не будет получен список не более чем из пяти комментариев. После этого мы снова обращаемся к списку, чтобы восстановить первоначальный порядок.

Деннис
источник
9

Pyth, 11 байт

_.-_Q<SQ_5

Мы рассчитываем пересечение мультимножества input ( Q) с пятью самыми большими элементами в Q(в порядке их появления Q), а затем возьмем первые пять из них.

_ .-           Reverse of multiset difference
     _ Q       of reversed Q
     <         with all but last 5 elements of sorted Q
       S Q                   
       _ 5

Попробуй это здесь .

lirtosiast
источник
<5SQэквивалентно тому <SQ_5, что сохраняет 1 байт.
PurkkaKoodari
Неа .
lirtosiast
Интересный. Интересно, почему это не реализовано как b[:-a]... Я думаю, что в какой-то момент это могло произойти.
PurkkaKoodari
5

MATL , 16 байт

tn4>?t_FT#S5:)S)

При этом используется текущая версия (10.2.1) , которая является более ранней, чем эта проблема.

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

объяснение

          % implicitly get input
t         % duplicate
n         % number of elements
4>?       % if greater than 4...
  t       % duplicate
  _       % unary minus (so that sorting will correspond to descending order)
  FT#S    % sort. Produce the indices of the sorting, not the sorted values
  5:)     % get first 5 indices
  S       % sort those indices, so that they correspond to original order in the input
  )       % index the input with those 5 indices
          % implicitly end if
          % implicitly display
Луис Мендо
источник
5

JavaScript, 74 65 62 61 байт

3 байта от спасибо @ user81655. 1 байт, спасибо @apsillers.

f=a=>5 in a?f(a.splice(a.lastIndexOf(Math.min(...a)),1)&&a):a

удален
источник
5

Питон 3, 76

Сохранено 9 байтов благодаря Кевину, напомнившему мне, что я могу злоупотреблять, если заявления в списке комп.

Сохранено 5 байт благодаря DSM.

Довольно простое решение прямо сейчас. Возьмите 5 лучших результатов, а затем проанализируйте список, добавив их в результат по мере их нахождения.

def f(x):y=sorted(x)[-5:];return[z for z in x if z in y and not y.remove(z)]

Вот мои тестовые случаи, если кто-то хочет их:

assert f([0, 2, 5, 4, 0, 1, 0]) == [0, 2, 5, 4, 1]
assert f([2, 1, 1, 5, 3, 6]) == [2, 1, 5, 3, 6]
assert f([0, 4, 5]) == [0, 4, 5]
assert f([0, 2, 0, 0, 0, 0, 0, 0]) == [0, 2, 0, 0, 0]
assert f([0, 0, 0, 0, 1, 0, 0, 0, 0]) == [0, 0, 0, 0, 1]
assert f([5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7]) == [5, 8, 7, 6, 7]
assert f([6, 3, 2, 0, 69, 22, 0, 37, 0, 2, 1, 0, 0, 0, 5, 0, 1, 2, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2]) == [6, 69, 22, 37, 5]
Морган Трепп
источник
4

05AB1E , 12 11 байт

Код:

E[Dg6‹#Rß\R

Объяснение:

E           # Evaluate input
 [          # Infinite loop
  D         # Duplicate top of the stack
   g        # Get the length
    6‹#     # If smaller than 6, break
       R    # Reverse top of the stack
        ß\  # Extract the smallest item and remove it
          R # Reverse top of the stack
            # Implicit, print the processed array

Использует кодировку CP-1252.

Аднан
источник
4

CJam, 16 байтов

{ee{1=~}$5<$1f=}

Безымянный блок (функция), который принимает массив и возвращает массив.

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

объяснение

ee   e# Enumerate the array, pairing each number with its index.
{    e# Sort by...
 1=  e#   The original value of each element.
 ~   e#   Bitwise NOT to sort from largest to smallest.
}$   e# This sort is stable, so the order tied elements is maintained.
5<   e# Discard all but the first five.
$    e# Sort again, this time by indices to recover original order.
1f=  e# Select the values, discarding the indices.
Мартин Эндер
источник
3

Утилиты Bash + GNU, 36

nl|sort -nrk2|sed 5q|sort -n|cut -f2

Ввод / вывод форматируется как разделенные новой строкой списки через STDIN / STDOUT.

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

Цифровая травма
источник
3

Python, 68 байт

lambda l,S=sorted:zip(*S(S(enumerate(l),key=lambda(i,x):-x)[:5]))[1]

Пример запуска.

Комок встроенных модулей. Я думаю, что лучший способ объяснить это - пробежаться по примеру.

>> l
[5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7]
>> enumerate(l)
[(0, 5), (1, 4), (2, 2), (3, 1), (4, 0), (5, 8), (6, 7), (7, 4), (8, 6), (9, 1), (10, 0), (11, 7)]

enumerateпревращает список в пары индекс / значение (технически enumerateобъект).

>> sorted(enumerate(l),key=lambda(i,x):-x)
[(5, 8), (6, 7), (11, 7), (8, 6), (0, 5), (1, 4), (7, 4), (2, 2), (3, 1), (9, 1), (4, 0), (10, 0)]
>> sorted(enumerate(l),key=lambda(i,x):-x)[:5]
[(5, 8), (6, 7), (11, 7), (8, 6), (0, 5)]

Сначала пары сортируются по наибольшему значению, сохраняя текущий порядок индекса для связей. Это ставит во главу угла самые высоко оцененные комментарии, сорванные ранее постом. Затем, 5 лучших таких комментариев принимаются.

>> sorted(_)
   [(0, 5), (5, 8), (6, 7), (8, 6), (11, 7)]
>> zip(*sorted(_))[1]
   (5, 8, 7, 6, 7)

Поместите пять лучших комментариев обратно в порядок публикации, а затем удалите индексы, сохраняя только баллы.

XNOR
источник
3

PowerShell v4, 120 97 байт

param($a)$b=@{};$a|%{$b.Add(++$d,$_)};($b.GetEnumerator()|sort Value|select -l 5|sort Name).Value

Экспериментируя вокруг, я нашел альтернативный подход, который добавил в игру некоторые дополнительные байты. Тем не менее, похоже, что это специфично для PowerShell v4 и того, как эта версия обрабатывает сортировку хеш-таблицы - по умолчанию кажется, что в v4, если несколько значений имеют одно и то же значение, он принимает значение с «более низким» ключом, но вы не гарантированы, что в v3 или ранее, даже при использовании упорядоченного ключевого слова в v3. Я не полностью проверял это на PowerShell v5, чтобы сказать, если поведение продолжается.

Эта версия только для v4 принимает входные данные как $a, а затем создает новую пустую хеш-таблицу $b. Мы перебираем все элементы ввода, $a|%{...}и каждая итерация добавляет пару ключ / значение $b(делается путем предварительного увеличения вспомогательной переменной $dв качестве ключа для каждой итерации). Тогда мы sort $bна основе Value, тоselect на -last 5, затем sortна Name(то есть ключе) и, наконец, выводим только.Value s из полученного хэша.

Если введено менее 5 элементов, он просто отсортирует по значению, выберет последние пять (то есть все из них), пересортирует по ключу и выведет.


Более старый, 120 байт, работает в более ранних версиях

param($a)if($a.Count-le5){$a;exit}[System.Collections.ArrayList]$b=($a|sort)[-5..-1];$a|%{if($_-in$b){$_;$b.Remove($_)}}

Тот же алгоритм, что и у Моргана Треппа ответе , что, очевидно, свидетельствует о том, что великие умы думают одинаково. :)

Принимает ввод, проверяет, меньше ли количество элементов или равно 5, и если да, выводит вход и выходит. В противном случае мы создаем ArrayList $b(с непомерно длинным [System.Collections.ArrayList]приведением) из пяти верхних элементов $a. Затем мы перебираем$a и для каждого элемента, если он есть, $bвыводим его, а затем удаляем из$b (и вот почему нам нужно использовать ArrayList, поскольку удаление элементов из массива не поддерживается в PowerShell, поскольку они технически исправлены размер).

Требуется v3 или выше для -inоператора. Для ответа , который работает в более ранних версиях, обмен $_-in$bна $b-contains$_в общей сложности 126 байт .

AdmBorkBork
источник
2

Haskell, 62 байта

import Data.List
map snd.sort.take 5.sortOn((0-).snd).zip[0..] 

Пример использования: map snd.sort.take 5.sortOn((0-).snd).zip[0..] $ [5, 4, 2, 1, 0, 8, 7, 4, 6, 1, 0, 7]-> [5,8,7,6,7].

Как это работает: дополнить каждый элемент индексом, отсортировать по убыванию, взять первые 5 элементов, отсортировать по индексу и удалить индекс.

Ними
источник
2

PHP 5, 107 102

Сохранено 5 байтов благодаря @WashingtonGuedes

function p($s){uasort($s,function($a,$b){return$a<=$b;});$t=array_slice($s,0,5,1);ksort($t);return$t;}

Ungolfed

function p($scores) {
    // sort the array from high to low,
    // keeping lower array keys on top of higher
    // array keys
    uasort($scores,function($a, $b){return $a <= $b;});
    // take the top 5
    $top_five = array_slice($scores,0,5,1);
    // sort by the keys
    ksort($top_five);
    return $top_five;
}

Попытайся.

Samsquanch
источник
Ибо 1 1 5 1 1 5, ваше представление производит вывод 1 5 1 1 5вместо правильного 1 1 5 1 5.
TNT
В PHP 7.X он работает по-разному, переключите версию PHP на 5.6 или ниже.
Samsquanch
Попался, не заметил номер версии. :)
TNT
Я тоже не поначалу. Я не уверен, почему это не спасает, какая версия использовалась так же как код. Я также не уверен, почему он не работает правильно на 7.X.
Samsquanch
@WashingtonGuedes Удаление пробелов сэкономило мне 5 байт, но я не вижу лишних точек с запятой, которые не выдавали бы ошибку?
Samsquanch
0

Руби, 82 87 89 байт

$><<eval($*[0]).map.with_index{|x,i|[i,x]}.sort_by{|x|-x[1]}[0,5].sort.map(&:last)

звонить: ruby test.rb [1,2,2,3,4,5]

исходная отправка - 56 байт, но в некоторых тестах она не выполняется и не поддерживает $ stdin и $ stdout

_.reduce([]){|a,x|a+=_.sort.reverse[0..4]&[x]if !a[4];a}

объяснение

$><<               # print to stdout
eval($*[0])        # evals the passed in array in stdin ex: [1,2,3,4]
.map.with_index    # returns an enumerator with indices
{|x,i|[i,x]}       # maps [index,value]
.sort_by{|x|-x[1]} # reverse sorts by the value
[0,5]              # selects the first 5 values
.sort              # sorts item by index (to find the place)
.map{|x|x[1]}      # returns just the values
Джон
источник
Хорошая программа. Возможно, вам придется спросить об этом ОП. Я не уверен, что формат ввода в порядке.
Rɪᴋᴇʀ
@RikerW на самом деле происходит сбой, когда в последнем индексе есть дублирующая вершина #, я сейчас ее модифицирую
Джон
@RikerW теперь исправлен, поддерживает stdin и пишет в stdout.
Джон
Хорошо. Мне нравится метод ввода, хотя. Я просто говорил спросить об этом @TNT.
Rɪᴋᴇʀ
0

Java 7, 155 байт

import java.util.*;List c(int[]f){LinkedList c=new LinkedList();for(int i:f)c.add(i);while(c.size()>5)c.removeLastOccurrence(Collections.min(c));return c;}

Ungolfed & тест-код:

Попробуй это здесь.

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

class Main{
    static List c(int[] f){
        LinkedList c = new LinkedList();
        for (int i : f){
            c.add(i);
        }
        while(c.size() > 5){
            c.removeLastOccurrence(Collections.min(c));
        }
        return c;
    }

    public static void main(String[] a){
        System.out.println(Arrays.toString(c(new int[]{ 0, 2, 5, 4, 0, 1, 0 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 2, 1, 1, 5, 3, 6 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 0, 4, 5 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 1, 1, 5, 1, 1, 5 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 0, 2, 0, 0, 0, 0, 0, 0 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 0, 0, 0, 0, 1, 0, 0, 0, 0 }).toArray()));
        System.out.println(Arrays.toString(c(new int[]{ 6, 3, 2, 0, 69, 22, 0, 37, 0, 2, 1, 0, 0, 0, 5, 0, 1, 2, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 2 }).toArray()));
    }
}

Выход:

[0, 2, 5, 4, 1]
[2, 1, 5, 3, 6]
[0, 4, 5]
[1, 1, 5, 1, 5]
[0, 2, 0, 0, 0]
[0, 0, 0, 0, 1]
[6, 69, 22, 37, 5]
Кевин Круйссен
источник
0

Юлия, 48 байт

!x=x[find(sum(x.<x',2)+diag(cumsum(x.==x')).<6)]

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

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

Комментарий c 1 имеет более высокий приоритет, чем комментарий c 2, если выполняется одно из следующих условий:

  • с 1 имеет больше голосов, чем с 2 .
  • c 1 и c 2 имеют одинаковое количество голосов, но c 1 был опубликован ранее.

Это определяет общий порядок комментариев, и задача состоит в том, чтобы найти пять комментариев, которые имеют наивысший приоритет.

Вместо сортировки комментариев по приоритету (что изменило бы их порядок, для каждого комментария c мы подсчитываем комментарии, которые имеют больший или равный приоритет. Мы сохраняем c тогда и только тогда, когда это число равно 5 или меньше.

Чтобы частично отсортировать комментарии по количеству голосов, мы делаем следующее. Пусть x будет вектором столбца, содержащим подсчет голосов. Затем x'транспонирует x - тем самым создавая вектор строки - и x.<x'создает булеву матрицу, которая сравнивает каждый элемент x с каждым элементом x T .

Для x = [0, 2, 5, 4, 0, 1, 0] это дает

<     0      2      5      4      0      1      0
0 false   true   true   true  false   true  false
2 false  false   true   true  false  false  false
5 false  false  false  false  false  false  false
4 false  false   true  false  false  false  false
0 false   true   true   true  false   true  false
1 false   true   true   true  false  false  false
0 false   true   true   true  false   true  false

Суммируя по строкам (через sum(...,2)), мы подсчитываем количество комментариев, которые имеют строго больше голосов, чем комментарий по этому индексу.

Для примера вектора это дает

4
2
0
1
4
3
4

Далее мы подсчитываем количество комментариев с равным количеством голосов, опубликованных ранее, чем этот комментарий. Мы достигаем этого следующим образом.

Сначала мы строим таблицу равенства с x.==x', что compraes элементов х с элементами х Т . Для нашего примера вектора это дает:

=     0      2      5      4      0      1      0
0  true  false  false  false   true  false   true
2 false   true  false  false  false  false  false
5 false  false   true  false  false  false  false
4 false  false  false   true  false  false  false
0  true  false  false  false   true  false   true
1 false  false  false  false  false   true  false
0  true  false  false  false   true  false   true

Далее мы используем cumsumдля расчета кумулятивных сумм каждого столбца матрицы.

1  0  0  0  1  0  1
1  1  0  0  1  0  1
1  1  1  0  1  0  1
1  1  1  1  1  0  1
2  1  1  1  2  0  2
2  1  1  1  2  1  2
3  1  1  1  3  1  3

Диагональ ( diag) содержит количество комментариев, которые имеют одинаковое количество голосов и происходят не позднее соответствующего комментария.

1
1
1
1
2
1
3

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

5
3
1
2
6
4
7

Комментарии с приоритетами от 1 до 5 должны отображаться, поэтому мы определяем их индексы с помощью find(....<6)и получаем соответствующие комментарии x[...].

Деннис
источник
0

Python 3.5, 68 байт

f=lambda x,*h:x and x[:sum(t>x[0]for t in x+h)<5]+f(x[1:],*h,x[0]+1)

Не подходит для моего ответа на Python 2 , но только на три байта длиннее его порта на Python 3, и я думаю, что он достаточно отличается, чтобы быть интересным.

Ввод / вывод в форме кортежей. Проверьте это на repl.it .

Деннис
источник