Mostrar as cinco principais pontuações de comentários em uma postagem do SE

30

Um script do Stack Exchange determina quais cinco comentários sobre perguntas ou respostas são vistos inicialmente na página principal dos sites através do número de votos positivos; os cinco comentários com o maior número de votos são exibidos. Sua tarefa é recriar esse comportamento.

Escreva um programa ou função completo, recebendo entradas através de STDIN, argumentos de linha de comando ou argumentos de função e imprima ou retorne as cinco principais pontuações de comentários. A entrada será uma matriz de números inteiros representando o número de votos positivos nos comentários de alguma postagem. Por exemplo, uma entrada de

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

significa que o primeiro comentário não tem votos, o segundo tem dois votos, o terceiro tem cinco, o quarto tem quatro, etc. A ordem das pontuações dos comentários deve permanecer a mesma no resultado.

Se a entrada contiver cinco ou menos pontuações de comentários, a saída deverá conter nada mais do que os dados. Se duas ou mais pontuações de comentários forem iguais, as primeiras pontuações devem ser exibidas. Você pode assumir que a matriz de entrada conterá pelo menos uma pontuação de comentário.

Os números na saída devem ser facilmente distinguidos (portanto, 02541 para o caso 1 é inválido). Caso contrário, não há restrições no formato de saída; os números podem ser separados por um espaço ou nova linha, ou podem estar no formato de lista etc.

Casos de teste:

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

O último exemplo foi retirado dessa pergunta de estouro de pilha .

Se possível, forneça um link em sua postagem para que seu envio possa ser executado on-line.

Este é o código golf, portanto o código mais curto em bytes vence. Boa sorte!

TNT
fonte
Devemos manter a ordem?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Sim. A ordem na qual os números inteiros aparecem não deve mudar.
TNT

Respostas:

10

Gelatina , 6 bytes

NỤḣ5Ṣị

Experimente online! ou verifique todos os casos de teste de uma só vez .

Como funciona

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.
Dennis
fonte
10

Python 2, 58 bytes

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

Teste em Ideone .

Como funciona

list.removeremove a primeira ocorrência se seu argumento da lista especificada. Ao reverter a lista x , basicamente conseguimos que ela remova a última ocorrência.

Portanto, basta remover o comentário com a quantidade mínima de votos até que uma lista de não mais que cinco comentários seja alcançada. Depois, revertemos a lista mais uma vez para restaurar o pedido original.

Dennis
fonte
9

Pitão, 11 bytes

_.-_Q<SQ_5

Calculamos a interseção multiset da entrada ( Q) com os cinco maiores elementos em Q(na ordem em que aparecem Q) e, em seguida, obtemos os cinco primeiros.

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

Experimente aqui .

lirtosiast
fonte
<5SQé equivalente a <SQ_5, o que economiza 1 byte.
PurkkaKoodari 27/01
Não .
precisa saber é o seguinte
Interessante. Eu me pergunto por que não foi implementado como b[:-a]... acho que pode ter sido isso em algum momento.
precisa saber é o seguinte
5

MATL , 16 bytes

tn4>?t_FT#S5:)S)

Isso usa a versão atual (10.2.1) , que é anterior a esse desafio.

Experimente online!

Explicação

          % 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
Luis Mendo
fonte
5

JavaScript, 74 65 62 61 bytes

3 bytes de desconto, graças a @ user81655. 1 byte de desconto, graças a @apsillers.

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

removido
fonte
5

Python 3, 76

Economizei 9 bytes graças a Kevin, lembrando-me que eu posso abusar das declarações if em uma lista comp.

Economizou 5 bytes graças ao DSM.

Solução bastante simples no momento. Pegue as 5 melhores pontuações e analise a lista adicionando-as ao resultado conforme as encontramos.

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

Aqui estão meus casos de teste, se alguém quiser:

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]
Morgan Thrapp
fonte
4

05AB1E , 12 11 bytes

Código:

E[Dg6‹#Rß\R

Explicação:

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

Usa a codificação CP-1252.

Adnan
fonte
4

CJam, 16 bytes

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

Um bloco sem nome (função) que pega uma matriz e retorna uma matriz.

Suíte de teste.

Explicação

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.
Martin Ender
fonte
3

Utilitários Bash + GNU, 36

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

E / S formatada como listas separadas por nova linha via STDIN / STDOUT.

Experimente online.

Trauma Digital
fonte
3

Python, 68 bytes

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

Exemplo de execução.

Um pedaço de embutidos. Eu acho que a melhor maneira de explicar é seguir um exemplo.

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

enumeratetransforma a lista em pares de índice / valor (tecnicamente um enumerateobjeto).

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

Os pares são classificados pelo maior valor primeiro, mantendo a ordem atual do índice para empates. Isso coloca na frente os comentários mais pontuados, quebrados por post anterior. Então, os 5 melhores comentários são feitos.

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

Coloque os cinco principais comentários de volta na ordem de postagem e remova os índices, mantendo apenas as pontuações.

xnor
fonte
3

PowerShell v4, 120 97 bytes

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

Experimentando, encontrei uma abordagem alternativa que gerava alguns bytes adicionais. No entanto, parece ser específico para o PowerShell v4 e como essa versão lida com a classificação de uma hashtable - parece, por padrão, que na v4, se vários valores tiverem o mesmo valor, leva aquele com uma chave "inferior", mas você não está garantido na v3 ou anterior, mesmo ao usar a palavra-chave ordenada na v3. Ainda não testei isso totalmente no PowerShell v5 para dizer se o comportamento continua.

Esta versão somente da v4 recebe entrada como $ae cria uma nova hashtable vazia $b. Percorremos todos os elementos da entrada $a|%{...}e cada iteração adiciona um par de chave / valor a $b(feito pré-incrementando uma variável auxiliar $dcomo a chave para cada iteração). Em seguida, sort $bbaseamos em Value, então selecto -last 5, depois sortem Name(ou seja, a chave) e, finalmente, produzimos apenas os .Values do hash resultante.

Se menos de 5 elementos forem inseridos, ele apenas classificará o valor, selecionará os cinco últimos (ou seja, todos), reordenará a chave e a saída.


Mais antigo, 120 bytes, funciona em versões anteriores

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

O mesmo algoritmo da resposta de Morgan Thrapp , que aparentemente é uma indicação de que grandes mentes pensam da mesma forma. :)

Recebe entrada, verifica se o número de itens é menor ou igual a 5 e, se assim for, gera a entrada e sai. Caso contrário, criamos um ArrayList $b(com o [System.Collections.ArrayList]elenco exorbitantemente longo ) dos cinco principais elementos de $a. Em seguida, iteramos sobre $ae para cada elemento, se estiver na $bsaída e o removemos $b(e aqui está o motivo pelo qual precisamos usar o ArrayList, pois remover elementos de um Array não é um recurso suportado no PowerShell, pois eles são tecnicamente corrigidos Tamanho).

Requer v3 ou superior para o -inoperador. Para uma resposta que funciona nas versões anteriores, troca $_-in$bpara $b-contains$_um total de 126 bytes .

AdmBorkBork
fonte
2

Haskell, 62 bytes

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

Exemplo de uso: 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].

Como funciona: aumente cada elemento com seu índice, classifique decrescente, pegue os 5 primeiros elementos, classifique por índice e remova o índice.

nimi
fonte
2

PHP 5, 107 102

Guardado 5 bytes graças a @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;
}

Tente.

Samsquanch
fonte
Pois 1 1 5 1 1 5, sua submissão produz uma saída em 1 5 1 1 5vez da correta 1 1 5 1 5.
TNT
Parece se comportar de maneira diferente no PHP 7.X, altere a versão do PHP para 5.6 ou abaixo.
Samsquanch
Entendi, não percebeu o número da versão. :)
TNT
Eu também não. Não sei por que isso não salva a versão usada e o código. Também não sei por que ele não funciona corretamente no 7.X.
Samsquanch
@WashingtonGuedes A remoção de espaços me salvou 5 bytes, mas não estou vendo ponto e vírgula desnecessário que não geraria um erro?
Samsquanch
0

Ruby, 82 87 89 bytes

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

chamar: ruby test.rb [1,2,2,3,4,5]

envio original - 56 bytes, mas falha em determinados casos de teste e não suportava $ stdin e $ stdout

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

Explicação

$><<               # 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
John
fonte
Bom programa. Você pode ter que perguntar ao OP sobre isso. Não tenho certeza se o formato de entrada está correto.
Rɪᴋᴇʀ
@RikerW ele realmente falhar quando há uma duplicata top # na última indice, estou modificando-o agora
John
O @RikerW está corrigido agora e suporta stdin e grava no stdout.
John
OK. Eu gosto do método de entrada embora. Eu estava dizendo para perguntar à @TNT sobre isso.
Rɪᴋᴇʀ
0

Java 7, 155 bytes

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 & test-code:

Experimente aqui.

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()));
    }
}

Saída:

[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]
Kevin Cruijssen
fonte
0

Julia, 48 bytes

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

Experimente online!

Como funciona

O comentário c 1 tem precedência mais alta que o comentário c 2 se um dos seguintes for verdadeiro:

  • c 1 tem mais votos positivos que c 2 .
  • c 1 e c 2 têm a mesma quantidade de votos positivos, mas c 1 foi postado anteriormente.

Isso define uma ordem total dos comentários, e a tarefa em questão é encontrar os cinco comentários que têm as precedências mais altas.

Em vez de classificar os comentários por precedência (o que alteraria sua ordem, para cada comentário c , contamos os comentários que têm uma precedência maior ou igual. Mantemos c se e somente se essa contagem for 5 ou menos.

Para classificar parcialmente os comentários por número de votos positivos, fazemos o seguinte. Seja x o vetor da coluna que contém a contagem de votos. Em seguida, x'transpõe x - criando, assim, um vector da linha - e x.<x'cria uma matriz booleano que compara cada um dos elementos de x , com cada elemento de x t .

Para x = [0, 2, 5, 4, 0, 1, 0] , isso fornece

<     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

Ao somar linhas (via sum(...,2)), contamos o número de comentários que têm estritamente mais votos que o comentário nesse índice.

Para o vetor de exemplo, isso fornece

4
2
0
1
4
3
4

Em seguida, contamos o número de comentários com uma quantidade igual de upvotes publicados antes desse comentário. Conseguimos isso da seguinte maneira.

Em primeiro lugar, construir uma tabela a igualdade com x.==x'que compraes os elementos de x com os elementos de x T . Para o nosso vetor de exemplo, isso fornece:

=     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

Em seguida, usamos cumsumpara calcular as somas cumulativas de cada coluna da matriz.

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

A diagonal ( diag) contém a contagem de comentários que têm uma quantidade igual de votos positivos e ocorrem o mais tardar no comentário correspondente.

1
1
1
1
2
1
3

Ao adicionar os dois vetores de linha que produzimos, obtemos as prioridades ( 1 é a mais alta) dos comentários.

5
3
1
2
6
4
7

Os comentários com prioridades que variam de 1 a 5 devem ser exibidos, para que determinemos seus índices find(....<6)e recuperemos os comentários correspondentes x[...].

Dennis
fonte
0

Python 3.5, 68 bytes

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

Não é páreo para a minha resposta do Python 2 , mas apenas três bytes a mais do que sua porta para o Python 3, e acho que é diferente o suficiente para ser interessante.

A E / S está na forma de tuplas. Testá-lo em repl.it .

Dennis
fonte